CSR-416 Fix merge conflict
This commit is contained in:
commit
5bc6ad16df
31 changed files with 2013 additions and 1196 deletions
|
|
@ -11,11 +11,9 @@ module.exports = {
|
|||
"!src/constants/*.js",
|
||||
"!src/router/**/*.js",
|
||||
"!src/helpers/unit-test-helper.js",
|
||||
"!src/helpers/damage-helper.js",
|
||||
"!src/layouts/component-test/component-test.vue",
|
||||
"!src/layouts/form-test/form-test.vue",
|
||||
"!src/layouts/vin-lookup/vin-lookup.vue",
|
||||
"!src/layouts/license-plate-lookup/license-plate-lookup.vue",
|
||||
"!src/layouts/vehicle-damage/windshield-damage-type-question/windshield-damage-type-question.vue",
|
||||
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
|
||||
"!src/layouts/part-questions/**/*.vue",
|
||||
|
|
@ -28,7 +26,6 @@ module.exports = {
|
|||
"!src/common-components/dropdown-question/dropdown-question.vue",
|
||||
"!src/common-components/textbox-question/textbox-question.vue",
|
||||
"!src/helpers/validation-rules.js",
|
||||
"!src/helpers/damage-helper.js",
|
||||
// END
|
||||
], //! means exclude from coverage.
|
||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||
|
|
|
|||
1257
package-lock.json
generated
1257
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<router-view></router-view>
|
||||
<router-view v-slot="{ Component }">
|
||||
<transition :duration="{ enter: 800, leave: 300 }" name="route-fade" mode="out-in">
|
||||
<component :is="Component" />
|
||||
</transition>
|
||||
</router-view>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
|||
BIN
src/assets/img/loader.gif
Normal file
BIN
src/assets/img/loader.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
src/assets/img/windshield.png
Normal file
BIN
src/assets/img/windshield.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1 KiB |
|
|
@ -162,7 +162,7 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.button-question-overflow {
|
||||
height: calc(100vh - 266px);
|
||||
height: calc(100vh - 274px);
|
||||
|
||||
.overflow-scroll {
|
||||
// Height will be determined by overall height of content above list
|
||||
|
|
|
|||
97
src/common-components/loading-modal/loading-modal.spec.js
Normal file
97
src/common-components/loading-modal/loading-modal.spec.js
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
import { shallowMount } from "@vue/test-utils";
|
||||
import loadingModal from "./loading-modal";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import store from "@/store";
|
||||
|
||||
jest.mock(
|
||||
"@/store",
|
||||
() => {
|
||||
return {};
|
||||
},
|
||||
{ virtual: true }
|
||||
);
|
||||
|
||||
jest.mock('@/assets/img/loader.gif', () => 'loader.gif')
|
||||
jest.mock('@/assets/img/windshield.png', () => 'windshield.png')
|
||||
|
||||
describe("loadingModal", () => {
|
||||
test("showModal sets modal visible", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ clickOutCloses: false });
|
||||
wrapper.vm.isModalVisible = false;
|
||||
|
||||
//Act
|
||||
wrapper.vm.showModal();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.isModalVisible).toEqual(true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
describe("loadingModal", () => {
|
||||
test("closeModal sets modal not visible", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ clickOutCloses: false });
|
||||
wrapper.vm.isModalVisible = true;
|
||||
|
||||
//Act
|
||||
wrapper.vm.closeModal();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.isModalVisible).toEqual(false);
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
describe("loadingModal", () => {
|
||||
test("canClose calls closeModal", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ clickOutCloses: true });
|
||||
wrapper.vm.isModalVisible = true;
|
||||
|
||||
//Act
|
||||
wrapper.vm.canClose();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.isModalVisible).toEqual(false);
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
describe("loadingModal", () => {
|
||||
test("canClose does not call closeModal", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ clickOutCloses: false });
|
||||
wrapper.vm.isModalVisible = true;
|
||||
|
||||
//Act
|
||||
wrapper.vm.canClose();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.isModalVisible).toEqual(true);
|
||||
wrapper.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({
|
||||
clickOutCloses
|
||||
}) {
|
||||
|
||||
//Mock store
|
||||
store.dispatch = jest.fn(() => {});
|
||||
store.getters = { };
|
||||
const mountOptions = getMountOptions({
|
||||
store: {
|
||||
dispatch: store.dispatch,
|
||||
getters: store.getters,
|
||||
},
|
||||
});
|
||||
|
||||
//Mock props
|
||||
mountOptions.propsData = { clickOutCloses: clickOutCloses };
|
||||
const wrapper = shallowMount(loadingModal, mountOptions);
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
126
src/common-components/loading-modal/loading-modal.vue
Normal file
126
src/common-components/loading-modal/loading-modal.vue
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<template>
|
||||
<div v-show="isModalVisible" class="loading-modal-backdrop" v-on:click="canClose" @close="closeModal">
|
||||
<div class="loading-modal">
|
||||
<button v-if="showCloseButton" type="button" class="loading-modal-close" @click="closeModal">x</button>
|
||||
<section class="loading-modal-body">
|
||||
<div class="modal-icon-container text-center">
|
||||
<img class="loader-gif" alt="Loading" src="@/assets/img/loader.gif">
|
||||
<img class="modal-icon" alt="" src="@/assets/img/windshield.png">
|
||||
</div>
|
||||
<div class="text-center fw-bold fs-5 loading-modal-text">
|
||||
<slot name="body">
|
||||
Default text
|
||||
</slot>
|
||||
</div>
|
||||
<div class="text-center fs-5 loading-modal-text">
|
||||
<slot name="subtext">
|
||||
Default subtext
|
||||
</slot>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Modal',
|
||||
data() {
|
||||
return {
|
||||
isModalVisible: false,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
showCloseButton: {type: Boolean, default: false},
|
||||
clickOutCloses: {type: Boolean, default: false},
|
||||
},
|
||||
methods: {
|
||||
showModal() {
|
||||
this.isModalVisible = true;
|
||||
},
|
||||
closeModal() {
|
||||
this.isModalVisible = false;
|
||||
},
|
||||
canClose() {
|
||||
this.clickOutCloses ? this.closeModal() : null;
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.loading-modal-backdrop {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #e5e5e5;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
z-index: 1050;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
.loading-modal {
|
||||
position: absolute;
|
||||
background: #ffffff;
|
||||
padding: 0 0 32px 0;
|
||||
box-shadow: 2px 2px 20px 1px;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.2);
|
||||
border-radius: 4px;
|
||||
top: 48px;
|
||||
height: 246px;
|
||||
width: 327px;
|
||||
}
|
||||
|
||||
.loading-modal-body {
|
||||
position: relative;
|
||||
padding: 20px 10px;
|
||||
}
|
||||
|
||||
.loading-modal-text {
|
||||
padding: 0 24px 0 24px;
|
||||
}
|
||||
|
||||
.loading-modal-close {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
font-weight: bold;
|
||||
color: $blue;
|
||||
background: transparent;
|
||||
z-index: 999;
|
||||
}
|
||||
|
||||
.modal-icon-container {
|
||||
position: relative;
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
margin: 15px auto;
|
||||
padding-bottom: 26px;
|
||||
}
|
||||
|
||||
.modal-icon-container img {
|
||||
position: absolute;
|
||||
vertical-align: middle;
|
||||
border: 0;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.loader-gif {
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -57,8 +57,13 @@ export default {
|
|||
const fieldOptions = {
|
||||
type: "text",
|
||||
value: props.modelValue,
|
||||
potentialInitialValue: props.modelValue,
|
||||
};
|
||||
|
||||
if (props.modelValue && props.modelValue.length > 0) {
|
||||
fieldOptions['initialValue'] = fieldOptions.potentialInitialValue;
|
||||
}
|
||||
|
||||
const {
|
||||
errorMessage,
|
||||
handleBlur,
|
||||
|
|
@ -98,10 +103,10 @@ export default {
|
|||
words.forEach(function (word) {
|
||||
const position = 1;
|
||||
word = [word.toString().slice(0, position), noBreakChar, word.toString().slice(position)].join('');
|
||||
questionText += `${word} `;
|
||||
});
|
||||
|
||||
questionText = questionText.trimEnd();
|
||||
questionText += `${word} `;
|
||||
});
|
||||
|
||||
questionText = questionText.trimEnd();
|
||||
} else {
|
||||
questionText = this.questionText.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,9 +3,33 @@ import baseMixin from "@/mixins/base-mixin.js";
|
|||
import { storeActions } from "@/constants/store-actions";
|
||||
|
||||
export function getDamageString() {
|
||||
return store.getters.damage.glassToReplace.length > 1 ? "match" : store.getters.damage.glassToReplace[0].location;
|
||||
const damageLocations = store.getters.damage.glassToReplace;
|
||||
let returnString;
|
||||
if(damageLocations.length > 1){
|
||||
returnString = "match"
|
||||
} else {
|
||||
switch(damageLocations[0]?.location) {
|
||||
case "Windshield":
|
||||
returnString = "windshield"
|
||||
break;
|
||||
case "Driver":
|
||||
case "Passenger":
|
||||
returnString = "side window"
|
||||
break;
|
||||
case "Rear":
|
||||
returnString = "rear window"
|
||||
}
|
||||
}
|
||||
return returnString;
|
||||
}
|
||||
|
||||
export function getIsWindshieldOnly () {
|
||||
const damageLocations = store.getters.damage.glassToReplace;
|
||||
const returnString = damageLocations.length === 1 && damageLocations[0]?.location === "Windshield" ? "windshield" : "glass";
|
||||
console.log(damageLocations);
|
||||
return returnString;
|
||||
}
|
||||
|
||||
export async function isGlassAvailableForCarId(carId){
|
||||
const newGlassOptions = await baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.GET_DAMAGE_OPTIONS,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,91 @@
|
|||
import {getDamageString, isGlassAvailableForCarId} from "./damage-helper";
|
||||
//import baseMixin from "@/mixins/base-mixin.js";
|
||||
import store from "@/store";
|
||||
|
||||
jest.mock("@/store", () => ({
|
||||
getters: {damage: {
|
||||
glassToReplace: [{location: "Windshield", name: "windshield"}]
|
||||
}
|
||||
}
|
||||
}));
|
||||
// Mock basemixin.
|
||||
jest.mock("@/mixins/base-mixin.js", () => ({
|
||||
methods: {
|
||||
dispatchStoreAction: jest.fn().mockImplementation(() => { return {
|
||||
data: {
|
||||
windshieldOptions: {availableReplacementOptions: ["windshield"]}
|
||||
}
|
||||
} }),
|
||||
},
|
||||
}));
|
||||
|
||||
describe("damage-helper.js", () => {
|
||||
it("Should return damage getter info", () => {
|
||||
it("Should return match when multiple selected damage options are in the store", () => {
|
||||
|
||||
// Arrange / Act
|
||||
store.getters.damage.glassToReplace = [{location: "Windshield", name: "windshield"}, {location: "Passenger", name: "sideWindow"}];
|
||||
|
||||
const damage = getDamageString();
|
||||
expect(damage).toEqual("Windshield")
|
||||
|
||||
// Assert
|
||||
expect(damage).toEqual("match");
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("damage-helper.js", () => {
|
||||
it("Should return windshield when Windshield is the only selected damage option in the store", () => {
|
||||
|
||||
// Arrange / Act
|
||||
store.getters.damage.glassToReplace = [{location: "Windshield", name: "windshield"}];
|
||||
|
||||
const damage = getDamageString();
|
||||
|
||||
// Assert
|
||||
expect(damage).toEqual("windshield");
|
||||
});
|
||||
});
|
||||
|
||||
describe("damage-helper.js", () => {
|
||||
it("Should return side window when Driver or Passenger is the only selected damage option in the store", () => {
|
||||
|
||||
// Arrange / Act
|
||||
store.getters.damage.glassToReplace = [{location: "Passenger", name: "sideWindow"}];
|
||||
|
||||
const damage = getDamageString();
|
||||
|
||||
// Assert
|
||||
expect(damage).toEqual("side window");
|
||||
});
|
||||
});
|
||||
|
||||
describe("damage-helper.js", () => {
|
||||
it("Should return rear window when Rear is the only selected damage option in the store", () => {
|
||||
|
||||
// Arrange / Act
|
||||
store.getters.damage.glassToReplace = [{location: "Rear", name: "rear"}];
|
||||
|
||||
const damage = getDamageString();
|
||||
|
||||
// Assert
|
||||
expect(damage).toEqual("rear window");
|
||||
});
|
||||
});
|
||||
|
||||
describe("damage-helper.js", () => {
|
||||
it("Should return true if no mismatches between each array exist", async () => {
|
||||
// Arrange
|
||||
store.getters.damage.glassToReplace = [{location: "Windshield", name: "windshield"}];
|
||||
|
||||
// Act
|
||||
const isGlassAvailable = await isGlassAvailableForCarId();
|
||||
|
||||
// Assert
|
||||
expect(isGlassAvailable).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("damage-helper.js", () => {
|
||||
it("Should return false if any mismatches between each array exist", async () => {
|
||||
// Arrange
|
||||
store.getters.damage.glassToReplace = [{location: "Windshield", name: "sideWindow"}];
|
||||
|
||||
const isGlassAvailable = await isGlassAvailableForCarId();
|
||||
|
||||
// Assert
|
||||
expect(isGlassAvailable).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -141,4 +141,4 @@ function isVinRelatedPage(toRoute) {
|
|||
fmgPageValue === fmgPageValues.ADDRESS_LOOKUP ||
|
||||
fmgPageValue === fmgPageValues.ADDRESS_VEHICLES ||
|
||||
fmgPageValue === fmgPageValues.ESTIMATE;
|
||||
}
|
||||
}
|
||||
|
|
@ -367,4 +367,4 @@ describe("navigateToHeritageFunnel", () => {
|
|||
})
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -5,54 +5,63 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
autocomplete="off" >
|
||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
|
||||
<div class="page-container-grouped-styles">
|
||||
<loadingModal :showCloseButton=false :clickOutCloses=false ref="loadingModal">
|
||||
<template v-slot:body>
|
||||
Please wait...
|
||||
</template>
|
||||
<template v-slot:subtext>
|
||||
This process can take up 20 seconds.
|
||||
</template>
|
||||
</loadingModal>
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage=false />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
|
||||
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
||||
<alert ref="alertVinNotFound" v-show="displayVinNotFoundAlert"
|
||||
class="my-3"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<alert ref="alertMatchedDifferentVehicle" v-show="displayMatchedDifferentVehicleAlert"
|
||||
class="my-3"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<alert ref="alertNonServiceableZip" v-show="displayNonServiceableZipAlert"
|
||||
class="my-3"
|
||||
alertClass="alert-danger"
|
||||
:manualHeadline="AlertNonServiceableZipHeader"
|
||||
:manualCopy="AlertNonServiceableZipBody"
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<alert ref="alertVinLookupsByHomeAddressNotAllowed" v-show="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||
class="my-3"
|
||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<textboxQuestion cmsWidgetName="ServiceZipQuestionWidget" v-model="serviceZip" ref="serviceZip" inputId="7add1b26df344f2caf1678de5797803f" aria-haspopup="" mask="#####" disableAutoFill validationRules="service-zip-required|service-zip-format" />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
||||
<alert ref="alertVinNotFound" v-show="displayVinNotFoundAlert"
|
||||
class="my-3"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<alert ref="alertMatchedDifferentVehicle" v-show="displayMatchedDifferentVehicleAlert"
|
||||
class="my-3"
|
||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||
alertClass="alert-warning"
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<alert ref="alertNonServiceableZip" v-show="displayNonServiceableZipAlert"
|
||||
class="my-3"
|
||||
alertClass="alert-danger"
|
||||
:manualHeadline="AlertNonServiceableZipHeader"
|
||||
:manualCopy="AlertNonServiceableZipBody"
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<alert ref="alertVinLookupsByHomeAddressNotAllowed" v-show="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||
class="my-3"
|
||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||
alertClass="alert-danger"
|
||||
v-bind:isDismissible="false"
|
||||
/>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
|
||||
<div class="row my-4">
|
||||
<div class="col">
|
||||
<textboxQuestion cmsWidgetName="ServiceZipQuestionWidget" v-model="serviceZip" ref="serviceZip" inputId="7add1b26df344f2caf1678de5797803f" aria-haspopup="" mask="#####" disableAutoFill validationRules="service-zip-required|service-zip-format" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
ref="funnelFooter"
|
||||
:isDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
/>
|
||||
|
||||
</transition>
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
ref="funnelFooter"
|
||||
:isDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
@ -67,6 +76,7 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he
|
|||
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
||||
import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
|
||||
|
||||
import { Form } from "vee-validate";
|
||||
import { defineRule } from "vee-validate";
|
||||
|
|
@ -250,6 +260,7 @@ export default {
|
|||
|
||||
// if the car entered is the same as the car found OR the glass options for the found car match the users damage selections
|
||||
if (carEntered.carId == carFound.carId || isGlassAvailableForCarId(carFound.carId)) {
|
||||
this.$refs.loadingModal.showModal();
|
||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||
} else {
|
||||
// if not then navigate to the "vehicle-damage" page
|
||||
|
|
@ -259,6 +270,7 @@ export default {
|
|||
// if multiple cars were found
|
||||
if (carsFound.find(car => car.carId === carEntered.carId)) {
|
||||
// and one of them matches the car id entered
|
||||
this.$refs.loadingModal.showModal();
|
||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||
} else {
|
||||
// and there is no match, navigate to "address-vehicle" page
|
||||
|
|
@ -358,6 +370,7 @@ export default {
|
|||
customerQuestions,
|
||||
textboxQuestion,
|
||||
alert,
|
||||
loadingModal,
|
||||
Form
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,29 +5,29 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
>
|
||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
|
||||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<buttonQuestion
|
||||
cmsWidgetName="VinLookupMethod"
|
||||
class="button-question-overflow"
|
||||
:questionText="questionText"
|
||||
:answers="answersFromCms"
|
||||
groupName="vinLookupMethodOption"
|
||||
buttonType="listButton"
|
||||
v-model="selectedValues"
|
||||
isRequired
|
||||
validationRules="option-required"
|
||||
/>
|
||||
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@isDisabled="!meta.valid"
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
/>
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<buttonQuestion
|
||||
cmsWidgetName="VinLookupMethod"
|
||||
:questionText="questionText"
|
||||
:answers="answersFromCms"
|
||||
groupName="vinLookupMethodOption"
|
||||
buttonType="listButton"
|
||||
v-model="selectedValues"
|
||||
isRequired
|
||||
validationRules="option-required"
|
||||
/>
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@isDisabled="!meta.valid"
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,17 +1,18 @@
|
|||
// Components
|
||||
import vehicleDamage from "@/layouts/license-plate-lookup/license-plate-lookup.vue";
|
||||
import licensePlateLookup from "@/layouts/license-plate-lookup/license-plate-lookup.vue";
|
||||
|
||||
// Supporting Files
|
||||
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
||||
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
|
||||
import baseMixin from "@/mixins/base-mixin";
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
import { shallowMount, flushPromises } from "@vue/test-utils";
|
||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import { nextTick } from "vue";
|
||||
import { storeActions } from "@/constants/store-actions";
|
||||
import { storeMutations } from "@/constants/store-mutations";
|
||||
import store from "@/store";
|
||||
import { validate } from "vee-validate";
|
||||
|
||||
jest.mock('@/assets/img/loader.gif', () => 'loader.gif')
|
||||
jest.mock('@/assets/img/windshield.png', () => 'windshield.png')
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||
|
|
@ -29,25 +30,15 @@ jest.mock("@/store", () => ({
|
|||
dispatch: jest.fn(),
|
||||
getters: {
|
||||
order: {
|
||||
customer: {
|
||||
emailAddress: "test@test.com"
|
||||
},
|
||||
serviceLocation: {
|
||||
zipCode: "43443"
|
||||
}
|
||||
customer: { emailAddress: "test@test.com"},
|
||||
serviceLocation: {zip: "11111"},
|
||||
},
|
||||
vehicle: {
|
||||
carId: "C00000000",
|
||||
image: "test.jpg",
|
||||
payment: {
|
||||
insuranceCoverage: {
|
||||
isVerified: false
|
||||
}
|
||||
},
|
||||
carId: "TESTID",
|
||||
registration: {
|
||||
licensePlate: "HWV4445",
|
||||
zipCode: "43224"
|
||||
}
|
||||
licensePlate: "TESTPLATE",
|
||||
zipCode: "12345",
|
||||
},
|
||||
},
|
||||
eventBusItem: jest.fn(),
|
||||
damage: {
|
||||
|
|
@ -62,7 +53,7 @@ describe("license-plate-lookup.vue", () => {
|
|||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
vehicleDamage.beforeRouteEnter.call(
|
||||
licensePlateLookup.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { fmgPage: "license-plate-lookup" } },
|
||||
undefined,
|
||||
|
|
@ -84,7 +75,7 @@ describe("license-plate-lookup.vue", () => {
|
|||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
vehicleDamage.beforeRouteEnter.call(
|
||||
licensePlateLookup.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { fmgPage: "license-plate-lookup" } },
|
||||
undefined,
|
||||
|
|
@ -99,6 +90,340 @@ describe("license-plate-lookup.vue", () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("getLicensePlateFromStore returns store license plate", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
// ACT
|
||||
const licensePlate = wrapper.vm.getLicensePlateFromStore();
|
||||
|
||||
// Assert
|
||||
expect(licensePlate).toEqual("TESTPLATE");
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("getRegistrationZipFromStore returns store registration zip", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
// ACT
|
||||
const registrationZip = wrapper.vm.getRegistrationZipFromStore();
|
||||
|
||||
// Assert
|
||||
expect(registrationZip).toEqual("12345");
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("getEmailFromStore returns store customer email", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
// ACT
|
||||
const customerEmail = wrapper.vm.getEmailFromStore();
|
||||
|
||||
// Assert
|
||||
expect(customerEmail).toEqual("test@test.com");
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("getServiceZipFromStore returns store service zip", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
// ACT
|
||||
const serviceZip = wrapper.vm.getServiceZipFromStore();
|
||||
|
||||
// Assert
|
||||
expect(serviceZip).toEqual("11111");
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("Navigate forward should be called and isCarId should be set to false when data entered matches store data on forwardButtonAction click", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
|
||||
return {data: {isServiceable: true}};
|
||||
});
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
const vinLookup = {data: {vehicle: {carId: "TESTID"}}}
|
||||
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
|
||||
return {catch: () => vinLookup};
|
||||
});
|
||||
wrapper.vm.navigateForward = jest.fn();
|
||||
|
||||
//Act
|
||||
licensePlateLookup.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { fmgPage: "license-plate-lookup" } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
|
||||
expect(wrapper.vm.isCarIdDifferent).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("Function should stop and datam isRegistrationZipServicable should be set to false when service zip entered returns false on forwardButtonAction click", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
|
||||
return {data: {isServiceable: false}};
|
||||
});
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
||||
//Act
|
||||
licensePlateLookup.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { fmgPage: "license-plate-lookup" } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.isRegistrationZipServicable).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("Function should stop and datam isCarIdDifferent should be set to true when carId entered doesn't match store carId or previously entered carId on forwardButtonAction click", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
|
||||
return {data: {isServiceable: true}};
|
||||
});
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
const vinLookup = {data: {vehicle: {carId: "TESTID1"}}}
|
||||
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
|
||||
return {catch: () => vinLookup};
|
||||
});
|
||||
wrapper.vm.$refs.funnelFooter.removeLoader = jest.fn();
|
||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||
|
||||
//Act
|
||||
licensePlateLookup.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { fmgPage: "license-plate-lookup" } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.isCarIdDifferent).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("Navigate forward should be called and isCarId should be set to true when carId entered matches previously entered carId and rest of data entered matches store data on forwardButtonAction click", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
wrapper.vm.validateZip = jest.fn().mockImplementation(() => {
|
||||
return {data: {isServiceable: true}};
|
||||
});
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
const vinLookup = {data: {vehicle: {carId: "TESTID1"}}}
|
||||
wrapper.vm.lookupVin = jest.fn().mockImplementation(() => {
|
||||
return {catch: () => vinLookup};
|
||||
});
|
||||
wrapper.vm.previouslyEnteredCarId = "TESTID1";
|
||||
wrapper.vm.navigateForward = jest.fn();
|
||||
|
||||
//Act
|
||||
licensePlateLookup.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { fmgPage: "license-plate-lookup" } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
|
||||
expect(wrapper.vm.isCarIdDifferent).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("Button Text should revert to initial value when licensePlate textfield has new text", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
wrapper.vm.licensePlate = "NEWPLATE";
|
||||
wrapper.vm.getCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("Button Text should revert to initial value when registrationZip textfield has new text", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
wrapper.vm.registrationZip = "55555";
|
||||
wrapper.vm.getCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("Button Text should revert to initial value when serviceZip textfield has new text", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
wrapper.vm.serviceZip = "55555";
|
||||
wrapper.vm.getCmsContent = jest.fn();
|
||||
wrapper.vm.$refs.funnelFooter.updateButtonText = jest.fn();
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.$refs.funnelFooter.updateButtonText).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("Dispatch reset damage and dependencies should be called if isCarIdDifferent is true and isSelectedGlassAvailableForVehicle is false when updateCustomerInfo is called", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
wrapper.vm.isCarIdDifferent = true;
|
||||
wrapper.vm.isSelectedGlassAvailableForVehicle = false;
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
store.commit = jest.fn();
|
||||
store.dispatch = jest.fn();
|
||||
|
||||
const vehicleInfo = {year: "2020", make: "honda", model: "civic", style: "2 door", carId: "TestId", category: "testCat", imageUrl: "image.jpg", imageVifNumber: "123", imageColor: "blue"}
|
||||
await wrapper.vm.updateCustomerInfo('vin', vehicleInfo, 'registrationState');
|
||||
|
||||
//Assert
|
||||
expect(store.dispatch).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("NavigateAfterSave should be called if isCarIdDifferent is true and isSelectedGlassAvailableForVehicle is false when navigateForward is called", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
wrapper.vm.isCarIdDifferent = true;
|
||||
wrapper.vm.isSelectedGlassAvailableForVehicle = false;
|
||||
wrapper.vm.$router.navigateAfterSave = jest.fn();
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
store.dispatch = jest.fn();
|
||||
|
||||
await wrapper.vm.navigateForward();
|
||||
|
||||
//Assert
|
||||
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("navigateAfterSaveToHeritageFunnel should be called if isCarIdDifferent is false or isSelectedGlassAvailableForVehicle is true when navigateForward is called", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
wrapper.vm.isCarIdDifferent = false;
|
||||
wrapper.vm.$refs.loadingModal.showModal = jest.fn();
|
||||
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
navigateToHeritage.navigateAfterSaveToHeritageFunnel = jest.fn();
|
||||
await wrapper.vm.navigateForward();
|
||||
|
||||
//Assert
|
||||
expect(navigateToHeritage.navigateAfterSaveToHeritageFunnel).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("dispatch non blocking store action called on validate zip", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
await wrapper.vm.validateZip("12345");
|
||||
|
||||
|
||||
//Assert
|
||||
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("license-plate-lookup.vue", () => {
|
||||
test("dispatch non blocking store action called on lookup vin", async () => {
|
||||
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
//Act
|
||||
await wrapper.vm.lookupVin("zzz123fqsfwg");
|
||||
|
||||
|
||||
//Assert
|
||||
expect(baseMixin.methods.dispatchStoreAction).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
function setupMocks({
|
||||
pageHeaderWidgetHeaderText = {},
|
||||
|
|
@ -106,12 +431,8 @@ function setupMocks({
|
|||
router: {
|
||||
navigate: jest.fn(),
|
||||
},
|
||||
store: {
|
||||
getters: {
|
||||
vehicle: {},
|
||||
payment: { insuranceCoverage: { isVerified: false } },
|
||||
},
|
||||
},
|
||||
licensePlate: "TESTPLATE",
|
||||
registrationZip: "12345"
|
||||
},
|
||||
}) {
|
||||
//Mock api responses
|
||||
|
|
@ -139,7 +460,7 @@ function setupMocks({
|
|||
const mountOptions = getMountOptions(mountOptionsMockData);
|
||||
mountOptions['attachTo'] = document.body; // append wrapper to document.body to test DOM methods
|
||||
|
||||
const wrapper = shallowMount(vehicleDamage, mountOptions);
|
||||
const wrapper = shallowMount(licensePlateLookup, mountOptions);
|
||||
|
||||
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,37 +1,48 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||
<div class="page-container-grouped-styles">
|
||||
<loadingModal :showCloseButton=false :clickOutCloses=false ref="loadingModal">
|
||||
<template v-slot:body>
|
||||
Please wait...
|
||||
</template>
|
||||
<template v-slot:subtext>
|
||||
This process can take up 20 seconds.
|
||||
</template>
|
||||
</loadingModal>
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion cmsWidgetName="LicensePlateNumber" v-model="licensePlate" isRequired inputId="license_plate" validationRules="license-plate-required" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<textboxQuestion cmsWidgetName="LicensePlateNumber" v-model="licensePlate" isRequired inputId="license_plate" validationRules="license-plate-required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion cmsWidgetName="RegistrationZip" v-model="registrationZip" inputId="zip" mask="#####" validationRules="zip-required" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<textboxQuestion cmsWidgetName="RegistrationZip" v-model="registrationZip" inputId="zip" mask="#####" validationRules="zip-required" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion cmsWidgetName="EmailAddress" v-model="email" inputId="email" validationRules="email-address-required|email-address-format" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<textboxQuestion cmsWidgetName="EmailAddress" v-model="email" inputId="email" validationRules="email-address-required|email-address-format" />
|
||||
</div>
|
||||
</div>
|
||||
<alert class="my-3" :manualHeadline="NoServiceZipHeader" :manualCopy="NoServiceZipBody" v-if="!isRegistrationZipServicable && isVinValid && !isCarIdDifferent" alertClass="alert-danger" />
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion v-if="!isRegistrationZipServicable" cmsWidgetName="ServiceZip" v-model="serviceZip" inputId="serviceZip" validationRules="zip-required" />
|
||||
</div>
|
||||
<div class="col">
|
||||
<textboxQuestion v-if="!isRegistrationZipServicable" cmsWidgetName="ServiceZip" v-model="serviceZip" inputId="serviceZip" validationRules="zip-required" />
|
||||
</div>
|
||||
</div>
|
||||
<alert class="my-3" cmsWidgetName="NoMatchAlertWidget" v-if="!isVinValid" alertClass="alert-danger" />
|
||||
<alert class="my-3" cmsWidgetName="NoMatchAlertWidget" v-if="!isVinValid" />
|
||||
<alert class="my-3" :manualHeadline="MatchedDifferentVehicleAlertHeader" :manualCopy="MatchedDifferentVehicleAlertBody" v-if="isCarIdDifferent" alertClass="alert-warning" />
|
||||
<funnelFooter ref="funnelFooter" cmsWidgetName="FunnelFooterWidget" :isForwardActionDisabled="!meta.valid" @back-clicked="backButtonAction" @ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</Form>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
||||
|
|
@ -40,310 +51,295 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
|||
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
||||
|
||||
import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
|
||||
// Supporting files
|
||||
import {
|
||||
fetchCmsContentForPage
|
||||
import {
|
||||
fetchCmsContentForPage
|
||||
} from "@/helpers/cms-content-helper";
|
||||
import {
|
||||
settleAllPromises
|
||||
settleAllPromises
|
||||
} from "@/helpers/layout-helper";
|
||||
import store from "@/store";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import {
|
||||
storeActions
|
||||
storeActions
|
||||
} from "@/constants/store-actions";
|
||||
import {
|
||||
storeMutations
|
||||
storeMutations
|
||||
} from "@/constants/store-mutations";
|
||||
import {
|
||||
errorMessages
|
||||
errorMessages
|
||||
} from "@/constants/error-messages";
|
||||
import {
|
||||
navigateAfterSaveToHeritageFunnel
|
||||
} from "@/helpers/heritage-integration/navigation-helper";
|
||||
import {
|
||||
getDamageString,
|
||||
isGlassAvailableForCarId,
|
||||
getDamageString,
|
||||
isGlassAvailableForCarId,
|
||||
} from "@/helpers/damage-helper";
|
||||
import {
|
||||
required,
|
||||
regex
|
||||
required,
|
||||
regex,
|
||||
} from "@/helpers/validation-rules";
|
||||
import {
|
||||
Form,
|
||||
defineRule
|
||||
Form,
|
||||
defineRule,
|
||||
} from "vee-validate";
|
||||
import {
|
||||
navigateAfterSaveToHeritageFunnel
|
||||
} from "@/helpers/heritage-integration/navigation-helper";
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule(
|
||||
"license-plate-required",
|
||||
required(errorMessages.LICENSE_PLATE_REQUIRED)
|
||||
"license-plate-required",
|
||||
required(errorMessages.LICENSE_PLATE_REQUIRED)
|
||||
);
|
||||
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
|
||||
defineRule(
|
||||
"email-address-required",
|
||||
required(errorMessages.EMAIL_ADDRESS_REQUIRED)
|
||||
"email-address-required",
|
||||
required(errorMessages.EMAIL_ADDRESS_REQUIRED)
|
||||
);
|
||||
defineRule(
|
||||
"email-address-format",
|
||||
regex(
|
||||
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/,
|
||||
errorMessages.EMAIL_ADDRESS_FORMAT
|
||||
)
|
||||
"email-address-format",
|
||||
regex(
|
||||
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+).([a-zA-Z]{2,})$/,
|
||||
errorMessages.EMAIL_ADDRESS_FORMAT
|
||||
)
|
||||
);
|
||||
|
||||
export default {
|
||||
name: "license-plate-lookup",
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
name: "license-plate-lookup",
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
}, ];
|
||||
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: "cmsContent",
|
||||
promise: cmsContentPromise,
|
||||
},
|
||||
];
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
props: {
|
||||
validationRules: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isRegistrationZipServicable: true,
|
||||
isVinValid: true,
|
||||
isCarIdDifferent: false,
|
||||
licensePlate: this.getLicensePlateFromStore(),
|
||||
registrationZip: this.getRegistrationZipFromStore(),
|
||||
email: this.getEmailFromStore(),
|
||||
serviceZip: this.getServiceZipFromStore(),
|
||||
previouslyEnteredCarId: "",
|
||||
customAlertData: {},
|
||||
isSelectedGlassAvailableForVehicle: true,
|
||||
zipToDisplay: this.getRegistrationZipFromStore(),
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.attachCustomEvents();
|
||||
},
|
||||
computed: {
|
||||
MatchedDifferentVehicleAlertHeader() {
|
||||
let text = this.getCmsContent(
|
||||
"MatchedDifferentVehicleAlertWidget",
|
||||
"HeadlineText"
|
||||
).replaceAll("{custom:damage}", getDamageString());
|
||||
return text;
|
||||
},
|
||||
props: {
|
||||
validationRules: String,
|
||||
MatchedDifferentVehicleAlertBody() {
|
||||
let text = this.getCmsContent(
|
||||
"MatchedDifferentVehicleAlertWidget",
|
||||
"BodyText"
|
||||
)
|
||||
.replaceAll("{custom:damage}", getDamageString())
|
||||
.replaceAll(
|
||||
"{custom:plateLookupYear}",
|
||||
this.customAlertData?.vehicleInfo?.year
|
||||
)
|
||||
.replaceAll(
|
||||
"{custom:plateLookupMake}",
|
||||
this.customAlertData?.vehicleInfo?.make
|
||||
)
|
||||
.replaceAll(
|
||||
"{custom:plateLookupModel}",
|
||||
this.customAlertData?.vehicleInfo?.model
|
||||
);
|
||||
return text;
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isRegistrationZipServicable: true,
|
||||
isVinValid: true,
|
||||
isCarIdDifferent: false,
|
||||
licensePlate: this.getLicensePlateFromStore(),
|
||||
registrationZip: this.getRegistrationZipFromStore(),
|
||||
email: this.getEmailFromStore(),
|
||||
serviceZip: this.getServiceZipFromStore(),
|
||||
previouslyEnteredCarId: "",
|
||||
customAlertData: {},
|
||||
isSelectedGlassAvailableForVehicle: true,
|
||||
};
|
||||
NoServiceZipHeader() {
|
||||
let text = this.getCmsContent(
|
||||
"NoServiceZipWidget",
|
||||
"HeadlineText"
|
||||
).replaceAll("{custom:zip}", this.zipToDisplay);
|
||||
return text;
|
||||
},
|
||||
mounted() {
|
||||
this.attachCustomEvents();
|
||||
NoServiceZipBody() {
|
||||
return this.getCmsContent("NoServiceZipWidget", "BodyText");
|
||||
},
|
||||
computed: {
|
||||
MatchedDifferentVehicleAlertHeader() {
|
||||
let text = this.getCmsContent(
|
||||
"MatchedDifferentVehicleAlertWidget",
|
||||
"HeadlineText"
|
||||
).replaceAll("{custom:damage}", getDamageString());
|
||||
|
||||
return text;
|
||||
},
|
||||
MatchedDifferentVehicleAlertBody() {
|
||||
let text = this.getCmsContent(
|
||||
"MatchedDifferentVehicleAlertWidget",
|
||||
"BodyText"
|
||||
)
|
||||
.replaceAll("{custom:damage}", getDamageString())
|
||||
.replaceAll(
|
||||
"{custom:plateLookupYear}",
|
||||
this.customAlertData?.vehicleInfo?.year
|
||||
)
|
||||
.replaceAll(
|
||||
"{custom:plateLookupMake}",
|
||||
this.customAlertData?.vehicleInfo?.make
|
||||
)
|
||||
.replaceAll(
|
||||
"{custom:plateLookupModel}",
|
||||
this.customAlertData?.vehicleInfo?.model
|
||||
);
|
||||
|
||||
return text;
|
||||
},
|
||||
NoServiceZipHeader() {
|
||||
let text = this.getCmsContent(
|
||||
"NoServiceZipWidget",
|
||||
"HeadlineText"
|
||||
).replaceAll("{custom:zip}", this.registrationZip);
|
||||
|
||||
return text;
|
||||
},
|
||||
NoServiceZipBody() {
|
||||
return this.getCmsContent("NoServiceZipWidget", "BodyText");
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return store.getters.vehicle.carId !== null;
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return store.getters.vehicle.carId !== null;
|
||||
},
|
||||
resetDependentState() {
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, null);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_CITY, null);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, null);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, null);
|
||||
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||
},
|
||||
attachCustomEvents() {
|
||||
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||
this.pushEventToGA(
|
||||
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||
this.GaActions.SUBMITTED,
|
||||
this.GaLabels.LICENSE_PLATE_LOOKUP,
|
||||
true
|
||||
);
|
||||
});
|
||||
},
|
||||
getLicensePlateFromStore() {
|
||||
return store.getters.vehicle.registration.licensePlate;
|
||||
},
|
||||
getRegistrationZipFromStore() {
|
||||
return store.getters.vehicle.registration.zipCode;
|
||||
},
|
||||
getEmailFromStore() {
|
||||
return store.getters.order.customer.emailAddress;
|
||||
},
|
||||
getServiceZipFromStore() {
|
||||
return store.getters.order.serviceLocation.zipCode
|
||||
},
|
||||
backButtonAction() {
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
const zipValidation = this.serviceZip ?
|
||||
await this.validateZip(this.serviceZip) :
|
||||
await this.validateZip(this.registrationZip);
|
||||
if (!zipValidation.data.isServiceable) {
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
this.isVinValid = true;
|
||||
this.isRegistrationZipServicable = false;
|
||||
this.isCarIdDifferent = false;
|
||||
return;
|
||||
}
|
||||
|
||||
const vinLookup = await this.lookupVin(
|
||||
this.licensePlate,
|
||||
zipValidation.data.state
|
||||
).catch(() => {
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
this.isVinValid = false;
|
||||
this.isCarIdDifferent = false;
|
||||
return;
|
||||
});
|
||||
|
||||
this.isCarIdDifferent =
|
||||
vinLookup.data.vehicle.carId !== store.getters.vehicle.carId;
|
||||
|
||||
if (
|
||||
this.isCarIdDifferent &&
|
||||
vinLookup.data.vehicle.carId !== this.previouslyEnteredCarId
|
||||
) {
|
||||
this.previouslyEnteredCarId = vinLookup.data.vehicle.carId;
|
||||
this.customAlertData.vehicleInfo = vinLookup.data.vehicle;
|
||||
this.$refs.funnelFooter.updateButtonText(
|
||||
`Continue with ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`
|
||||
);
|
||||
this.isVinValid = true;
|
||||
this.isSelectedGlassAvailableForVehicle =
|
||||
await isGlassAvailableForCarId(vinLookup.data.vehicle.carId);
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateCustomerInfo(
|
||||
vinLookup.data.vin,
|
||||
vinLookup.data.vehicle,
|
||||
zipValidation.data.state
|
||||
);
|
||||
|
||||
const partsData = await baseMixin.methods.dispatchStoreAction(
|
||||
this.storeActions.GET_PARTS_OR_QUESTIONS, {
|
||||
carId: vinLookup.data.vehicle.carId,
|
||||
glassArray: this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle ? [] : store.getters.damage.glassToReplace,
|
||||
zipCode: this.serviceZip ? this.serviceZip : this.registrationZip,
|
||||
vin: vinLookup.data.vin,
|
||||
},
|
||||
false
|
||||
);
|
||||
this.navigateForward(partsData);
|
||||
},
|
||||
navigateForward(partsData) {
|
||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||
this.$router.navigateAfterSave(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route, {}, {
|
||||
displayVehicleChangeAlert: true
|
||||
},
|
||||
partsData.data
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||
return;
|
||||
}
|
||||
},
|
||||
validateZip(zip) {
|
||||
return baseMixin.methods.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
||||
zip,
|
||||
});
|
||||
},
|
||||
lookupVin(plate, state) {
|
||||
return baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.LOOKUP_VIN_BY_PLATE, {
|
||||
licensePlate: plate,
|
||||
licenseState: state
|
||||
}
|
||||
);
|
||||
},
|
||||
updateCustomerInfo(vin, vehicleInfo, registrationState) {
|
||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||
}
|
||||
console.log("A")
|
||||
console.log(this.licensePlate)
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
|
||||
store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);
|
||||
store.commit(storeMutations.UPDATE_MAKE, vehicleInfo.make);
|
||||
store.commit(storeMutations.UPDATE_MODEL, vehicleInfo.model);
|
||||
store.commit(storeMutations.UPDATE_STYLE, vehicleInfo.style);
|
||||
store.commit(storeMutations.UPDATE_CAR_ID, vehicleInfo.carId);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicleInfo.category);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, vehicleInfo.imageUrl);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicleInfo.imageVifNumber);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicleInfo.imageColor);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, this.licensePlate);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.registrationZip);
|
||||
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZip);
|
||||
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
|
||||
},
|
||||
resetDependentState() {
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_ADDRESS, null);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_CITY, null);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, null);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, null);
|
||||
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||
},
|
||||
watch: {
|
||||
licensePlate() {
|
||||
this.$refs.funnelFooter.updateButtonText(
|
||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||
);
|
||||
},
|
||||
registrationZip() {
|
||||
this.$refs.funnelFooter.updateButtonText(
|
||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||
);
|
||||
},
|
||||
serviceZip() {
|
||||
this.$refs.funnelFooter.updateButtonText(
|
||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||
);
|
||||
},
|
||||
attachCustomEvents() {
|
||||
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||
this.pushEventToGA(
|
||||
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||
this.GaActions.SUBMITTED,
|
||||
this.GaLabels.LICENSE_PLATE_LOOKUP,
|
||||
true
|
||||
);
|
||||
});
|
||||
},
|
||||
components: {
|
||||
Form,
|
||||
funnelHeader,
|
||||
vehicleBanner,
|
||||
funnelSubHeader,
|
||||
textboxQuestion,
|
||||
alert,
|
||||
funnelFooter,
|
||||
getLicensePlateFromStore() {
|
||||
return store.getters.vehicle.registration.licensePlate;
|
||||
},
|
||||
getRegistrationZipFromStore() {
|
||||
return store.getters.vehicle.registration.zipCode;
|
||||
},
|
||||
getEmailFromStore() {
|
||||
return store.getters.order.customer.emailAddress;
|
||||
},
|
||||
getServiceZipFromStore() {
|
||||
return store.getters.order.serviceLocation.zip;
|
||||
},
|
||||
backButtonAction() {
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
const zipValidation = this.serviceZip ?
|
||||
await this.validateZip(this.serviceZip) :
|
||||
await this.validateZip(this.registrationZip);
|
||||
if (!zipValidation.data.isServiceable) {
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
this.isVinValid = true;
|
||||
this.isRegistrationZipServicable = false;
|
||||
this.isCarIdDifferent = false;
|
||||
this.zipToDisplay = this.serviceZip ? this.serviceZip : this.registrationZip;
|
||||
return;
|
||||
}
|
||||
const vinLookup = await this.lookupVin(
|
||||
this.licensePlate,
|
||||
zipValidation.data.state
|
||||
).catch(() => {
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
this.isVinValid = false;
|
||||
this.isCarIdDifferent = false;
|
||||
return;
|
||||
});
|
||||
this.isCarIdDifferent =
|
||||
vinLookup.data.vehicle.carId !== store.getters.vehicle.carId;
|
||||
|
||||
if (
|
||||
this.isCarIdDifferent &&
|
||||
vinLookup.data.vehicle.carId !== this.previouslyEnteredCarId
|
||||
) {
|
||||
this.previouslyEnteredCarId = vinLookup.data.vehicle.carId;
|
||||
this.customAlertData.vehicleInfo = vinLookup.data.vehicle;
|
||||
this.$refs.funnelFooter.updateButtonText(
|
||||
`Continue with ${vinLookup.data.vehicle.year} ${vinLookup.data.vehicle.make} ${vinLookup.data.vehicle.model}`
|
||||
);
|
||||
this.isVinValid = true;
|
||||
this.isSelectedGlassAvailableForVehicle =
|
||||
await isGlassAvailableForCarId(vinLookup.data.vehicle.carId);
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateCustomerInfo(
|
||||
vinLookup.data.vin,
|
||||
vinLookup.data.vehicle,
|
||||
zipValidation.data.state
|
||||
);
|
||||
|
||||
this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||
this.$router.navigateAfterSave(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route,
|
||||
{},
|
||||
{ displayVehicleChangeAlert: true },
|
||||
{}
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
this.$refs.loadingModal.showModal();
|
||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||
return;
|
||||
}
|
||||
},
|
||||
validateZip(zip) {
|
||||
return baseMixin.methods.dispatchStoreAction(storeActions.VALIDATE_ZIP, {
|
||||
zip,
|
||||
});
|
||||
},
|
||||
lookupVin(plate, state) {
|
||||
return baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.LOOKUP_VIN_BY_PLATE,
|
||||
{ licensePlate: plate, licenseState: state }
|
||||
);
|
||||
},
|
||||
updateCustomerInfo(vin, vehicleInfo, registrationState) {
|
||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||
}
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
|
||||
store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);
|
||||
store.commit(storeMutations.UPDATE_MAKE, vehicleInfo.make);
|
||||
store.commit(storeMutations.UPDATE_MODEL, vehicleInfo.model);
|
||||
store.commit(storeMutations.UPDATE_STYLE, vehicleInfo.style);
|
||||
store.commit(storeMutations.UPDATE_CAR_ID, vehicleInfo.carId);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicleInfo.category);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, vehicleInfo.imageUrl);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, vehicleInfo.imageVifNumber);
|
||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicleInfo.imageVifColor);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, this.licensePlate);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState);
|
||||
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.registrationZip);
|
||||
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZip);
|
||||
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.email);
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
licensePlate() {
|
||||
this.$refs.funnelFooter.updateButtonText(
|
||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||
);
|
||||
},
|
||||
registrationZip() {
|
||||
this.$refs.funnelFooter.updateButtonText(
|
||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||
);
|
||||
},
|
||||
serviceZip() {
|
||||
this.$refs.funnelFooter.updateButtonText(
|
||||
this.getCmsContent("FunnelFooterWidget", "ForwardButtonText")
|
||||
);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
Form,
|
||||
funnelHeader,
|
||||
vehicleBanner,
|
||||
funnelSubHeader,
|
||||
textboxQuestion,
|
||||
alert,
|
||||
funnelFooter,
|
||||
loadingModal,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
</script>
|
||||
|
|
@ -1,12 +1,14 @@
|
|||
<template>
|
||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall">
|
||||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage=false />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<h1>Part Questions Page Placeholder</h1>
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget" @back-clicked="backButtonAction"
|
||||
/>
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<h1>Part Questions Page Placeholder</h1>
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget" @back-clicked="backButtonAction"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -5,61 +5,63 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
>
|
||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
|
||||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage=false />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<alert
|
||||
ref="vehicleChangeAlert"
|
||||
class="mt-5 mb-0"
|
||||
cmsWidgetName="VehicleChangeAlert"
|
||||
v-show="shouldDisplayVehicleChangeAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
<damageLocationQuestion
|
||||
ref="damageLocation"
|
||||
cmsWidgetName="DamageLocationQuestion"
|
||||
v-model="selectedDamageLocations"
|
||||
groupName="DamageLocationQuestion"
|
||||
/>
|
||||
<windshieldOptions
|
||||
ref="windshieldOptions"
|
||||
v-model="selectedWindshieldOptions"
|
||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
cmsWidgetName="HasReplacementConflict"
|
||||
v-show="hasRepairReplaceConflict"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
<sideDoorOptions
|
||||
ref="sideDoorOptions"
|
||||
cmsWidgetName="SideDoorSideQuestion"
|
||||
groupName="SideDoorSideQuestion"
|
||||
v-model="sideDoorOptionsData"
|
||||
v-show="!hasRepairReplaceConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
/>
|
||||
<replaceOptionsQuestion
|
||||
ref="backGlassOptions"
|
||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
||||
v-model="selectedRearReplaceOptions"
|
||||
groupName="BackGlassReplaceOptionsQuestion"
|
||||
validationRules="replace-options-required"
|
||||
/>
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
:isBackButtonHidden=shouldHideBackButton
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
/>
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<alert
|
||||
ref="vehicleChangeAlert"
|
||||
class="mt-5 mb-0"
|
||||
cmsWidgetName="VehicleChangeAlert"
|
||||
v-show="shouldDisplayVehicleChangeAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
<damageLocationQuestion
|
||||
ref="damageLocation"
|
||||
cmsWidgetName="DamageLocationQuestion"
|
||||
v-model="selectedDamageLocations"
|
||||
groupName="DamageLocationQuestion"
|
||||
/>
|
||||
<windshieldOptions
|
||||
ref="windshieldOptions"
|
||||
v-model="selectedWindshieldOptions"
|
||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
cmsWidgetName="HasReplacementConflict"
|
||||
v-show="hasRepairReplaceConflict"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
<sideDoorOptions
|
||||
ref="sideDoorOptions"
|
||||
cmsWidgetName="SideDoorSideQuestion"
|
||||
groupName="SideDoorSideQuestion"
|
||||
v-model="sideDoorOptionsData"
|
||||
v-show="!hasRepairReplaceConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
/>
|
||||
<replaceOptionsQuestion
|
||||
ref="backGlassOptions"
|
||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
||||
v-model="selectedRearReplaceOptions"
|
||||
groupName="BackGlassReplaceOptionsQuestion"
|
||||
validationRules="replace-options-required"
|
||||
/>
|
||||
<funnel-footer
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
:isBackButtonHidden=shouldHideBackButton
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<buttonQuestion
|
||||
class="radioQuestion"
|
||||
class="radioQuestion"
|
||||
isOverflowScrollable
|
||||
selectingInitiatesLoad
|
||||
:questionText="questionText"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="container-fluid shadow rounded-3 p-0 position-relative make-tall">
|
||||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="select-car-form rounded text-center">
|
||||
|
|
@ -10,7 +10,9 @@
|
|||
backButtonAccessibleText="Change Vehicle Year"
|
||||
@click-event="backButtonAction"
|
||||
/>
|
||||
<makeQuestion v-model="selectedMake" ref="makeQuestion" cmsWidgetName="VehicleMakeQuestion" />
|
||||
<div class="fade-on-route-transition">
|
||||
<makeQuestion v-model="selectedMake" ref="makeQuestion" cmsWidgetName="VehicleMakeQuestion" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="container-fluid shadow rounded-3 p-0 position-relative">
|
||||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="select-car-form rounded text-center">
|
||||
|
|
@ -10,7 +10,9 @@
|
|||
backButtonAccessibleText="Change Vehicle Make"
|
||||
@click-event="backButtonAction"
|
||||
/>
|
||||
<modelQuestion v-model="selectedModel" ref="modelQuestion" cmsWidgetName="VehicleModelQuestion" />
|
||||
<div class="fade-on-route-transition">
|
||||
<modelQuestion v-model="selectedModel" ref="modelQuestion" cmsWidgetName="VehicleModelQuestion" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,36 +1,38 @@
|
|||
<template>
|
||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall">
|
||||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader ref="funnelHeader" cmsWidgetName="FunnelHeaderWidget" />
|
||||
<vehicleBanner ref="vehicleBanner" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
||||
<funnelSubHeader ref="funnelSubHeader" cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<div class="container-fluid prevent-squish my-5">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<alert
|
||||
class="rounded border-0 shadow-sm"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="AlertWidget"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<div class="container-fluid prevent-squish my-5">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<alert
|
||||
class="rounded border-0 shadow-sm"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="AlertWidget"
|
||||
:isDismissible="false"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-for="(item, i) in PartsForQuestions" :key="i">
|
||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||
<div class="container-fluid">
|
||||
<hr v-if="i > 0" />
|
||||
<div v-for="(item, i) in PartsForQuestions" :key="i">
|
||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||
<div class="container-fluid">
|
||||
<hr v-if="i > 0" />
|
||||
</div>
|
||||
|
||||
<glassPartQuestion
|
||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||
v-model="glassParts[item.glassLocation + '-' + item.glassName]"
|
||||
:glassLocation="item.glassLocation"
|
||||
:glassName="item.glassName"
|
||||
:colorAnswers="item.colorAnswers"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<glassPartQuestion
|
||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||
v-model="glassParts[item.glassLocation + '-' + item.glassName]"
|
||||
:glassLocation="item.glassLocation"
|
||||
:glassName="item.glassName"
|
||||
:colorAnswers="item.colorAnswers"
|
||||
/>
|
||||
<funnelFooter cmsWidgetName="FunnelFooterWidget" ref="funnelFooter" @back-clicked="backButtonAction" @ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
<funnelFooter cmsWidgetName="FunnelFooterWidget" ref="funnelFooter" @back-clicked="backButtonAction" @ForwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
<template>
|
||||
<div class="container-fluid shadow rounded-3 p-0 position-relative">
|
||||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="select-car-form rounded text-center">
|
||||
|
|
@ -10,7 +10,9 @@
|
|||
backButtonAccessibleText="Change Vehicle Model"
|
||||
@click-event="backButtonAction"
|
||||
/>
|
||||
<styleQuestion v-model="selectedStyle" ref="styleQuestion" cmsWidgetName="VehicleStyleQuestion" />
|
||||
<div class="fade-on-route-transition">
|
||||
<styleQuestion v-model="selectedStyle" ref="styleQuestion" cmsWidgetName="VehicleStyleQuestion" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,18 @@
|
|||
<template>
|
||||
<div class="container-fluid shadow rounded-3 p-0 position-relative">
|
||||
<div class="page-container-grouped-styles">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<div class="select-car">
|
||||
<div class="select-car-form rounded text-center">
|
||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<yearQuestion v-model="selectedYear" ref="yearQuestion" cmsWidgetName="VehicleYearQuestion" />
|
||||
<div class="fade-on-route-transition">
|
||||
<yearQuestion
|
||||
class="fade-on-route-transition"
|
||||
v-model="selectedYear"
|
||||
ref="yearQuestion"
|
||||
cmsWidgetName="VehicleYearQuestion"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -5,73 +5,133 @@
|
|||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
>
|
||||
<div
|
||||
class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5"
|
||||
>
|
||||
<div class="page-container-grouped-styles">
|
||||
<loadingModal :showCloseButton=false :clickOutCloses=false ref="loadingModal">
|
||||
<template v-slot:body>
|
||||
Please wait...
|
||||
</template>
|
||||
<template v-slot:subtext>
|
||||
This process can take up 20 seconds.
|
||||
</template>
|
||||
</loadingModal>
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||
<vehicleBanner
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false"
|
||||
/>
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="VinNumber"
|
||||
v-model="vin"
|
||||
inputId="vin"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
validationRules="vin-required|vin-format"
|
||||
:isDisabled="isVinFieldReadOnly"
|
||||
/>
|
||||
<div class="fade-on-route-transition sub-container make-tall">
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="VinNumber"
|
||||
v-model="vin"
|
||||
inputId="vin"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
validationRules="vin-required|vin-format"
|
||||
:isDisabled="isVinFieldReadOnly"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<vinInformation />
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<vinInformation />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="ServiceZIP"
|
||||
v-model="zip"
|
||||
inputId="zip"
|
||||
mask="#####"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
validationRules="zip-required"
|
||||
/>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="ServiceZIP"
|
||||
v-model="zip"
|
||||
inputId="zip"
|
||||
mask="#####"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
validationRules="zip-required"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="EmailAddress"
|
||||
v-model="email"
|
||||
inputId="email"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
validationRules="email-address-required|email-address-format"
|
||||
/>
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
cmsWidgetName="EmailAddress"
|
||||
v-model="email"
|
||||
inputId="email"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
validationRules="email-address-required|email-address-format"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<alert
|
||||
class="my-3"
|
||||
:manualHeadline="MatchedDifferentVehicleAlertHeader"
|
||||
:manualCopy="MatchedDifferentVehicleAlertBody"
|
||||
v-model="customAlertData"
|
||||
v-if="matchedDifferentVehicle"
|
||||
alertClass="alert-danger"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
v-model="customAlertData"
|
||||
v-if="noMatchAlert"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="NoMatchAlertWidget"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
:manualHeadline="NoServiceZipHeader"
|
||||
:manualCopy="NoServiceZipBody"
|
||||
v-model="customAlertData"
|
||||
v-if="noServiceZip"
|
||||
alertClass="alert-warning"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
v-model="customAlertData"
|
||||
v-if="foundWindshieldAlert"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="FoundWindshieldAlert"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
v-model="customAlertData"
|
||||
v-if="vinNotFound"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="VinNotFound"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
v-model="customAlertData"
|
||||
v-if="perfectMatchNewVinAlert"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="PerfectMatchNewVinAlert"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
:manualHeadline="PerfectMatchNewVinAlertReadOnlyHeader"
|
||||
:manualCopy="PerfectMatchNewVinAlertReadOnlyBody"
|
||||
v-model="customAlertData"
|
||||
v-if="isVinFieldReadOnly"
|
||||
alertClass="alert-success"
|
||||
/>
|
||||
<funnelFooter
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
ref="funnelFooter"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
/>
|
||||
</div>
|
||||
<alert
|
||||
class="my-3"
|
||||
:manualHeadline="MatchedDifferentVehicleAlertHeader"
|
||||
:manualCopy="MatchedDifferentVehicleAlertBody"
|
||||
v-model="customAlertData"
|
||||
v-if="matchedDifferentVehicle"
|
||||
v-if="isCarIdDifferent"
|
||||
alertClass="alert-danger"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
v-model="customAlertData"
|
||||
v-if="noMatchAlert"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="NoMatchAlertWidget"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
:manualHeadline="NoServiceZipHeader"
|
||||
|
|
@ -80,13 +140,6 @@
|
|||
v-if="noServiceZip"
|
||||
alertClass="alert-warning"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
v-model="customAlertData"
|
||||
v-if="foundWindshieldAlert"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="FoundWindshieldAlert"
|
||||
/>
|
||||
<alert
|
||||
class="my-3"
|
||||
v-model="customAlertData"
|
||||
|
|
@ -98,16 +151,9 @@
|
|||
class="my-3"
|
||||
v-model="customAlertData"
|
||||
v-if="perfectMatchNewVinAlert"
|
||||
alertClass="alert-warning"
|
||||
alertClass="alert-success"
|
||||
cmsWidgetName="PerfectMatchNewVinAlert"
|
||||
/>
|
||||
<funnelFooter
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
ref="funnelFooter"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@back-clicked="backButtonAction"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
/>
|
||||
</div>
|
||||
</Form>
|
||||
</template>
|
||||
|
|
@ -121,6 +167,7 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he
|
|||
import alert from "@/ux-components/alert/alert";
|
||||
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
||||
import vinInformation from "@/layouts/vin-lookup/vin-information/vin-information";
|
||||
import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||
|
|
@ -130,7 +177,7 @@ import baseMixin from "@/mixins/base-mixin.js";
|
|||
import { storeActions } from "@/constants/store-actions";
|
||||
import { storeMutations } from "@/constants/store-mutations";
|
||||
import { errorMessages } from "@/constants/error-messages";
|
||||
import { getDamageString, isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
||||
import { getDamageString, getIsWindshieldOnly, isGlassAvailableForCarId } from "@/helpers/damage-helper";
|
||||
import { required, regex } from "@/helpers/validation-rules";
|
||||
import { Form, defineRule } from "vee-validate";
|
||||
// import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||
|
|
@ -177,44 +224,39 @@ export default {
|
|||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
props: {
|
||||
validationRules: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
matchedDifferentVehicle: false,
|
||||
noMatchAlert: false,
|
||||
isCarIdDifferent: false,
|
||||
noServiceZip: false,
|
||||
vinFound: false,
|
||||
vinFoundReadOnly: false,
|
||||
foundWindshieldAlert: false,
|
||||
vinNotFound: false,
|
||||
perfectMatchNewVinAlert: false,
|
||||
vin: this.getVinFromStore(),
|
||||
zip: this.getZipFromStore(),
|
||||
email: this.getEmailFromStore(),
|
||||
customAlertData: {},
|
||||
isCarIdDifferent: false,
|
||||
previouslyEnteredCarId: '',
|
||||
invalidZip: '',
|
||||
vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
perfectMatchNewVinAlert() {
|
||||
return this.vinPopulatedOnPageLoad && this.vin === this.getVinFromStore();
|
||||
},
|
||||
MatchedDifferentVehicleAlertHeader(){
|
||||
let text = this.getCmsContent("MatchedDifferentVehicle",
|
||||
const text = this.getCmsContent("MatchedDifferentVehicle",
|
||||
"HeadlineText").replaceAll("{custom:damage}", getDamageString());
|
||||
|
||||
return text;
|
||||
},
|
||||
MatchedDifferentVehicleAlertBody(){
|
||||
let text = this.getCmsContent("MatchedDifferentVehicle",
|
||||
const text = this.getCmsContent("MatchedDifferentVehicle",
|
||||
"BodyText").replaceAll("{custom:damage}", getDamageString()).replaceAll("{custom:vinlookupYear}", this.customAlertData?.vehicleInfo?.year).replaceAll("{custom:vinlookupMake}", this.customAlertData?.vehicleInfo?.make).replaceAll("{custom:vinlookupModel}",
|
||||
this.customAlertData?.vehicleInfo?.model);
|
||||
|
||||
return text;
|
||||
},
|
||||
NoServiceZipHeader(){
|
||||
let text = this.getCmsContent("NoServiceZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", this.invalidZip);
|
||||
const text = this.getCmsContent("NoServiceZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", this.invalidZip);
|
||||
|
||||
return text;
|
||||
},
|
||||
|
|
@ -228,6 +270,13 @@ export default {
|
|||
return this.getCmsContent("PerfectMatchNewVinAlert", "BodyText").replaceAll("{custom:damage}",
|
||||
getDamageString())
|
||||
},
|
||||
PerfectMatchNewVinAlertReadOnlyHeader () {
|
||||
return this.getCmsContent("PerfectMatchNewVinAlertReadOnly", "HeadlineText");
|
||||
},
|
||||
PerfectMatchNewVinAlertReadOnlyBody () {
|
||||
return this.getCmsContent("PerfectMatchNewVinAlertReadOnly", "BodyText").replaceAll("{custom:damage}",
|
||||
getIsWindshieldOnly())
|
||||
},
|
||||
isVinFieldReadOnly(){
|
||||
return this.$store.getters.payment.insuranceCoverage.isVerified;
|
||||
},
|
||||
|
|
@ -302,7 +351,7 @@ export default {
|
|||
this.isVinValid = true;
|
||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vehicleLookup.data.carId);
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
this.matchedDifferentVehicle = true;
|
||||
this.isCarIdDifferent = true;
|
||||
return;
|
||||
}
|
||||
this.updateStore(vehicleLookup.data);
|
||||
|
|
@ -320,6 +369,7 @@ export default {
|
|||
this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD, this.$route, {}, { displayVehicleChangeAlert: true }, {});
|
||||
return;
|
||||
} else {
|
||||
this.$refs.loadingModal.showModal();
|
||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||
return;
|
||||
}
|
||||
|
|
@ -362,6 +412,7 @@ export default {
|
|||
alert,
|
||||
funnelFooter,
|
||||
vinInformation,
|
||||
loadingModal,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -102,19 +102,11 @@ const routingTable = [
|
|||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.REVEAL,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.VIN_LOOKUP,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
}
|
||||
],
|
||||
},
|
||||
|
|
@ -125,18 +117,6 @@ const routingTable = [
|
|||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CONTINUING_WITH_PARTS_QUESTION,
|
||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CONTINUING_WITH_MULTIPLE_PARTS,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CONTINUING_WITH_SINGLE_PART,
|
||||
destinationFmgPageValue: fmgPageValues.REVEAL,
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
|
|
@ -157,7 +137,7 @@ const routingTable = [
|
|||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{fmgPageValue: fmgPageValues.ESTIMATE,
|
||||
|
|
|
|||
|
|
@ -145,9 +145,9 @@ export const mutations = {
|
|||
updateRegistrationAddress(state, registrationAddress){
|
||||
state.order.vehicle.registration.address = registrationAddress;
|
||||
},
|
||||
updateServiceLocationZipCode(state, serviceLocationZipCode){
|
||||
state.order.serviceLocation.zipCode = serviceLocationZipCode;
|
||||
},
|
||||
updateServiceLocationZipCode(state, serviceLocationZip){
|
||||
state.order.vehicle.registration.zip = serviceLocationZip;
|
||||
},
|
||||
updateRegistrationCity(state, serviceCity){
|
||||
state.order.vehicle.registration.city = serviceCity;
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,4 +9,22 @@
|
|||
.fade-enter-from,
|
||||
.fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.route-fade-enter-active .fade-on-route-transition {
|
||||
transition: opacity 0.8s ease;
|
||||
}
|
||||
|
||||
.route-fade-leave-active .fade-on-route-transition {
|
||||
transition: opacity 0.3s ease;
|
||||
}
|
||||
|
||||
.route-fade-enter-from .fade-on-route-transition,
|
||||
.route-fade-leave-to .fade-on-route-transition {
|
||||
/*
|
||||
Hack around a Chrome 96 bug in handling nested opacity transitions.
|
||||
This is not needed in other browsers or Chrome 99+ where the bug
|
||||
has been fixed.
|
||||
*/
|
||||
opacity: 0.001;
|
||||
}
|
||||
|
|
@ -26,6 +26,15 @@ body {
|
|||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.sub-container{
|
||||
&.make-tall {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
left: -10000px;
|
||||
|
|
@ -34,4 +43,8 @@ body {
|
|||
height: 1px;
|
||||
overflow: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.page-container-grouped-styles {
|
||||
@extend .container-fluid, .shadow, .rounded-3, .p-2, .position-relative, .make-tall, .px-5;
|
||||
}
|
||||
}
|
||||
|
|
@ -47,6 +47,21 @@ describe("alert.vue", () => {
|
|||
expect(wrapperDiv.classes()).toContain('warning')
|
||||
});
|
||||
|
||||
it("Should update alert Headline to manualHeadline datam entered and alert copy to manualCopy datam entered when no cmsWidgetName entered", async () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(alert, {
|
||||
propsData: {
|
||||
manualHeadline: 'testHeader',
|
||||
manualCopy: 'testCopy'
|
||||
},
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.alertHeadline).toBe("testHeader");
|
||||
expect(wrapper.vm.alertCopy).toBe("testCopy");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
const mockMixin = {
|
||||
|
|
|
|||
Loading…
Reference in a new issue