Merge branch 'develop' into feature/CSR-18
This commit is contained in:
commit
83c649fc8d
41 changed files with 1912 additions and 1186 deletions
|
|
@ -30,6 +30,7 @@ resources:
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
- group: Digital-Infrastructure
|
- group: Digital-Infrastructure
|
||||||
|
- group: FixMyGlass-BuildBranches
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
# PR's
|
# PR's
|
||||||
|
|
@ -47,6 +48,7 @@ stages:
|
||||||
# Dev Build/Deploy
|
# Dev Build/Deploy
|
||||||
- ${{ else }}:
|
- ${{ else }}:
|
||||||
- stage: Dev
|
- stage: Dev
|
||||||
|
condition: eq(variables['Build.SourceBranch'], variables['dev-branch'] )
|
||||||
variables:
|
variables:
|
||||||
- group: FixMyGlassDev
|
- group: FixMyGlassDev
|
||||||
jobs:
|
jobs:
|
||||||
|
|
@ -88,6 +90,7 @@ stages:
|
||||||
|
|
||||||
# QA Build/Deploy
|
# QA Build/Deploy
|
||||||
- stage: Qa
|
- stage: Qa
|
||||||
|
condition: eq(variables['Build.SourceBranch'], variables['qa-branch'] )
|
||||||
variables:
|
variables:
|
||||||
- group: FixMyGlassQa
|
- group: FixMyGlassQa
|
||||||
jobs:
|
jobs:
|
||||||
|
|
@ -121,4 +124,7 @@ stages:
|
||||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||||
|
indexDeployVariables:
|
||||||
|
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||||
|
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||||
cfDistributionId: $(cfDistributionId)
|
cfDistributionId: $(cfDistributionId)
|
||||||
|
|
@ -11,11 +11,9 @@ module.exports = {
|
||||||
"!src/constants/*.js",
|
"!src/constants/*.js",
|
||||||
"!src/router/**/*.js",
|
"!src/router/**/*.js",
|
||||||
"!src/helpers/unit-test-helper.js",
|
"!src/helpers/unit-test-helper.js",
|
||||||
"!src/helpers/damage-helper.js",
|
|
||||||
"!src/layouts/component-test/component-test.vue",
|
"!src/layouts/component-test/component-test.vue",
|
||||||
"!src/layouts/form-test/form-test.vue",
|
"!src/layouts/form-test/form-test.vue",
|
||||||
"!src/layouts/vin-lookup/vin-lookup.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-damage-type-question/windshield-damage-type-question.vue",
|
||||||
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
|
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
|
||||||
"!src/layouts/part-questions/**/*.vue",
|
"!src/layouts/part-questions/**/*.vue",
|
||||||
|
|
@ -28,7 +26,6 @@ module.exports = {
|
||||||
"!src/common-components/dropdown-question/dropdown-question.vue",
|
"!src/common-components/dropdown-question/dropdown-question.vue",
|
||||||
"!src/common-components/textbox-question/textbox-question.vue",
|
"!src/common-components/textbox-question/textbox-question.vue",
|
||||||
"!src/helpers/validation-rules.js",
|
"!src/helpers/validation-rules.js",
|
||||||
"!src/helpers/damage-helper.js",
|
|
||||||
// END
|
// END
|
||||||
], //! means exclude from coverage.
|
], //! means exclude from coverage.
|
||||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
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>
|
<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>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<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>
|
<style lang="scss" scoped>
|
||||||
.button-question-overflow {
|
.button-question-overflow {
|
||||||
height: calc(100vh - 266px);
|
height: calc(100vh - 274px);
|
||||||
|
|
||||||
.overflow-scroll {
|
.overflow-scroll {
|
||||||
// Height will be determined by overall height of content above list
|
// Height will be determined by overall height of content above list
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,8 @@ export default {
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const fieldOptions = {
|
const fieldOptions = {
|
||||||
type: "text",
|
type: "text",
|
||||||
value: props.modelValue,
|
value: props.modelValue,
|
||||||
|
initialValue: props.modelValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
|
||||||
47
src/common-components/loading-modal/loading-modal.spec.js
Normal file
47
src/common-components/loading-modal/loading-modal.spec.js
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
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();
|
||||||
|
wrapper.vm.isModalVisible = false;
|
||||||
|
|
||||||
|
//Act
|
||||||
|
wrapper.vm.showModal();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.isModalVisible).toEqual(true);
|
||||||
|
wrapper.unmount();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function setupMocks() {
|
||||||
|
|
||||||
|
//Mock store
|
||||||
|
store.dispatch = jest.fn(() => {});
|
||||||
|
store.getters = { };
|
||||||
|
const mountOptions = getMountOptions({
|
||||||
|
store: {
|
||||||
|
dispatch: store.dispatch,
|
||||||
|
getters: store.getters,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const wrapper = shallowMount(loadingModal, mountOptions);
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
97
src/common-components/loading-modal/loading-modal.vue
Normal file
97
src/common-components/loading-modal/loading-modal.vue
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
<template>
|
||||||
|
<div v-show="isModalVisible" class="loading-modal-backdrop">
|
||||||
|
<div class="loading-modal">
|
||||||
|
<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">
|
||||||
|
Please wait...
|
||||||
|
</div>
|
||||||
|
<div class="text-center fs-5 loading-modal-text">
|
||||||
|
This process can take up to 20 seconds.
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'Modal',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isModalVisible: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
showModal() {
|
||||||
|
this.isModalVisible = true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</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;
|
||||||
|
}
|
||||||
|
|
||||||
|
.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>
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="textbox-question" :class="(errors && errors.length) || hasError ? 'has-error' : ''">
|
<div class="textbox-question" :class="(errors && errors.length) || hasError ? 'has-error' : ''">
|
||||||
<label :for="inputId" :aria-label="questionText" class="form-label" v-html="labelText"></label>
|
<label :for="inputId" :aria-label="questionText" class="form-label" v-html="labelText"></label>
|
||||||
<input v-model="value"
|
<input
|
||||||
|
v-model="value"
|
||||||
v-maska="mask"
|
v-maska="mask"
|
||||||
:type="type"
|
:type="type"
|
||||||
class="form-control"
|
class="form-control"
|
||||||
|
|
@ -15,8 +16,7 @@
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
:class="[hasIcon ? 'has-icon' : '', iconRight ? 'icon-right' : '']"
|
:class="[hasIcon ? 'has-icon' : '', iconRight ? 'icon-right' : '']"
|
||||||
:validationRules="validationRules"
|
:validationRules="validationRules"
|
||||||
@change="handleChange"
|
/>
|
||||||
@blur="handleBlur" />
|
|
||||||
<div v-show="errorMessage" class="row mt-2 form-test-error">
|
<div v-show="errorMessage" class="row mt-2 form-test-error">
|
||||||
<span role="alert">{{ errorMessage }}</span>
|
<span role="alert">{{ errorMessage }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -51,12 +51,26 @@ export default {
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
cmsWidgetName: String,
|
cmsWidgetName: String
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
const propsClone = Object.assign({}, props);
|
||||||
|
const modelValue = propsClone.modelValue;
|
||||||
|
let initialValue;
|
||||||
|
|
||||||
|
switch (typeof modelValue) {
|
||||||
|
case "number":
|
||||||
|
initialValue = modelValue;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
initialValue = (modelValue && modelValue.length > 0) ? modelValue : "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
const fieldOptions = {
|
const fieldOptions = {
|
||||||
type: "text",
|
type: "text",
|
||||||
value: props.modelValue,
|
value: modelValue,
|
||||||
|
initialValue: initialValue
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {
|
||||||
|
|
@ -98,10 +112,10 @@ export default {
|
||||||
words.forEach(function (word) {
|
words.forEach(function (word) {
|
||||||
const position = 1;
|
const position = 1;
|
||||||
word = [word.toString().slice(0, position), noBreakChar, word.toString().slice(position)].join('');
|
word = [word.toString().slice(0, position), noBreakChar, word.toString().slice(position)].join('');
|
||||||
questionText += `${word} `;
|
questionText += `${word} `;
|
||||||
});
|
});
|
||||||
|
|
||||||
questionText = questionText.trimEnd();
|
questionText = questionText.trimEnd();
|
||||||
} else {
|
} else {
|
||||||
questionText = this.questionText.toString();
|
questionText = this.questionText.toString();
|
||||||
}
|
}
|
||||||
|
|
@ -110,6 +124,11 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
watch: {
|
||||||
|
value(newValue) {
|
||||||
|
this.handleChange(newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -117,6 +136,7 @@ export default {
|
||||||
.textbox-question {
|
.textbox-question {
|
||||||
label {
|
label {
|
||||||
color: $black;
|
color: $black;
|
||||||
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
input {
|
input {
|
||||||
&.has-icon {
|
&.has-icon {
|
||||||
|
|
@ -161,4 +181,4 @@ export default {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -13,6 +13,7 @@ const errorMessages = {
|
||||||
ZIP_REQUIRED: "Please enter your ZIP",
|
ZIP_REQUIRED: "Please enter your ZIP",
|
||||||
ZIP_FORMAT: "Please enter a valid ZIP",
|
ZIP_FORMAT: "Please enter a valid ZIP",
|
||||||
LICENSE_PLATE_REQUIRED: "Please enter your license plate number",
|
LICENSE_PLATE_REQUIRED: "Please enter your license plate number",
|
||||||
|
REGISTRATION_ZIP_REQUIRED: "Please enter your registration ZIP code",
|
||||||
FIRST_NAME_REQUIRED: "Please enter your first name",
|
FIRST_NAME_REQUIRED: "Please enter your first name",
|
||||||
LAST_NAME_REQUIRED: "Please enter your last name",
|
LAST_NAME_REQUIRED: "Please enter your last name",
|
||||||
EMAIL_ADDRESS_REQUIRED: "Please enter your email address",
|
EMAIL_ADDRESS_REQUIRED: "Please enter your email address",
|
||||||
|
|
@ -20,7 +21,7 @@ const errorMessages = {
|
||||||
SERVICE_ZIP_REQUIRED: "Please enter your Service ZIP",
|
SERVICE_ZIP_REQUIRED: "Please enter your Service ZIP",
|
||||||
SERVICE_ZIP_FORMAT: "Please enter a valid Service ZIP",
|
SERVICE_ZIP_FORMAT: "Please enter a valid Service ZIP",
|
||||||
VIN_REQUIRED: "Please enter your VIN",
|
VIN_REQUIRED: "Please enter your VIN",
|
||||||
VIN_FORMAT: "Please enter a valid VIN",
|
VIN_FORMAT: "Invalid VIN. Please make sure that you entered the correct 17-digit, alpha-numeric number. VINs do not contain the letters I, O, or Q",
|
||||||
OPTION_REQUIRED: "Please select an option",
|
OPTION_REQUIRED: "Please select an option",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,32 @@ import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
|
||||||
export function getDamageString() {
|
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";
|
||||||
|
return returnString;
|
||||||
|
}
|
||||||
|
|
||||||
export async function isGlassAvailableForCarId(carId){
|
export async function isGlassAvailableForCarId(carId){
|
||||||
const newGlassOptions = await baseMixin.methods.dispatchStoreAction(
|
const newGlassOptions = await baseMixin.methods.dispatchStoreAction(
|
||||||
storeActions.GET_DAMAGE_OPTIONS,
|
storeActions.GET_DAMAGE_OPTIONS,
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,91 @@
|
||||||
import {getDamageString, isGlassAvailableForCarId} from "./damage-helper";
|
import {getDamageString, isGlassAvailableForCarId} from "./damage-helper";
|
||||||
//import baseMixin from "@/mixins/base-mixin.js";
|
import store from "@/store";
|
||||||
|
|
||||||
jest.mock("@/store", () => ({
|
// Mock basemixin.
|
||||||
getters: {damage: {
|
jest.mock("@/mixins/base-mixin.js", () => ({
|
||||||
glassToReplace: [{location: "Windshield", name: "windshield"}]
|
methods: {
|
||||||
}
|
dispatchStoreAction: jest.fn().mockImplementation(() => { return {
|
||||||
}
|
data: {
|
||||||
}));
|
windshieldOptions: {availableReplacementOptions: ["windshield"]}
|
||||||
|
}
|
||||||
|
} }),
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
describe("damage-helper.js", () => {
|
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();
|
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);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -140,4 +140,4 @@ function isVinRelatedPage(toRoute) {
|
||||||
fmgPageValue === fmgPageValues.ADDRESS_LOOKUP ||
|
fmgPageValue === fmgPageValues.ADDRESS_LOOKUP ||
|
||||||
fmgPageValue === fmgPageValues.ADDRESS_VEHICLES ||
|
fmgPageValue === fmgPageValues.ADDRESS_VEHICLES ||
|
||||||
fmgPageValue === fmgPageValues.ESTIMATE;
|
fmgPageValue === fmgPageValues.ESTIMATE;
|
||||||
}
|
}
|
||||||
|
|
@ -367,4 +367,4 @@ describe("navigateToHeritageFunnel", () => {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
@ -5,54 +5,56 @@
|
||||||
ref="theForm"
|
ref="theForm"
|
||||||
v-slot="{ meta }"
|
v-slot="{ meta }"
|
||||||
autocomplete="off" >
|
autocomplete="off" >
|
||||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5">
|
<div class="page-container-grouped-styles">
|
||||||
|
<loadingModal ref="loadingModal"/>
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||||
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage=false />
|
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage=false />
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" ref="funnelSubHeader" />
|
||||||
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
<alert ref="alertVinNotFound" v-show="displayVinNotFoundAlert"
|
<customerQuestions ref="customerQuestions" v-model="customerQuestions" />
|
||||||
class="my-3"
|
<alert ref="alertVinNotFound" v-show="displayVinNotFoundAlert"
|
||||||
cmsWidgetName="AlertVinNotFoundWidget"
|
class="my-3"
|
||||||
alertClass="alert-danger"
|
cmsWidgetName="AlertVinNotFoundWidget"
|
||||||
v-bind:isDismissible="false"
|
alertClass="alert-danger"
|
||||||
/>
|
v-bind:isDismissible="false"
|
||||||
<alert ref="alertMatchedDifferentVehicle" v-show="displayMatchedDifferentVehicleAlert"
|
/>
|
||||||
class="my-3"
|
<alert ref="alertMatchedDifferentVehicle" v-show="displayMatchedDifferentVehicleAlert"
|
||||||
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
class="my-3"
|
||||||
:manualCopy="AlertMatchedDifferentVehicleBody"
|
:manualHeadline="AlertMatchedDifferentVehicleHeader"
|
||||||
alertClass="alert-warning"
|
:manualCopy="AlertMatchedDifferentVehicleBody"
|
||||||
v-bind:isDismissible="false"
|
alertClass="alert-warning"
|
||||||
/>
|
v-bind:isDismissible="false"
|
||||||
<alert ref="alertNonServiceableZip" v-show="displayNonServiceableZipAlert"
|
/>
|
||||||
class="my-3"
|
<alert ref="alertNonServiceableZip" v-show="displayNonServiceableZipAlert"
|
||||||
alertClass="alert-danger"
|
class="my-3"
|
||||||
:manualHeadline="AlertNonServiceableZipHeader"
|
alertClass="alert-danger"
|
||||||
:manualCopy="AlertNonServiceableZipBody"
|
:manualHeadline="AlertNonServiceableZipHeader"
|
||||||
v-bind:isDismissible="false"
|
:manualCopy="AlertNonServiceableZipBody"
|
||||||
/>
|
v-bind:isDismissible="false"
|
||||||
<alert ref="alertVinLookupsByHomeAddressNotAllowed" v-show="displayVinLookupByHomeAddressNotAllowedAlert"
|
/>
|
||||||
class="my-3"
|
<alert ref="alertVinLookupsByHomeAddressNotAllowed" v-show="displayVinLookupByHomeAddressNotAllowedAlert"
|
||||||
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
class="my-3"
|
||||||
alertClass="alert-danger"
|
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
|
||||||
v-bind:isDismissible="false"
|
alertClass="alert-danger"
|
||||||
/>
|
v-bind:isDismissible="false"
|
||||||
<transition name="fade" mode="out-in">
|
/>
|
||||||
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
|
<transition name="fade" mode="out-in">
|
||||||
<div class="row my-4">
|
<div class="service-zip-field" v-if="showServiceZipField" aria-live="polite">
|
||||||
<div class="col">
|
<div class="row my-4">
|
||||||
<textboxQuestion cmsWidgetName="ServiceZipQuestionWidget" v-model="serviceZip" ref="serviceZip" inputId="7add1b26df344f2caf1678de5797803f" aria-haspopup="" mask="#####" disableAutoFill validationRules="service-zip-required|service-zip-format" />
|
<div class="col">
|
||||||
|
<textboxQuestion cmsWidgetName="ServiceZipQuestionWidget" v-model="serviceZipCode" ref="serviceZip" inputId="7add1b26df344f2caf1678de5797803f" aria-haspopup="" mask="#####" disableAutoFill validationRules="service-zip-required|service-zip-format" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</transition>
|
||||||
</transition>
|
<funnel-footer
|
||||||
<funnel-footer
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
ref="funnelFooter"
|
||||||
ref="funnelFooter"
|
:isDisabled="!meta.valid"
|
||||||
:isDisabled="!meta.valid"
|
@ForwardClicked="forwardButtonAction"
|
||||||
@ForwardClicked="forwardButtonAction"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
/>
|
||||||
/>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -67,6 +69,7 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he
|
||||||
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
|
import customerQuestions from "@/layouts/address-lookup/customer-questions/customer-questions";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
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 { Form } from "vee-validate";
|
||||||
import { defineRule } from "vee-validate";
|
import { defineRule } from "vee-validate";
|
||||||
|
|
@ -115,19 +118,22 @@ export default {
|
||||||
streetAddress: this.getRegistrationAddressFromStore(),
|
streetAddress: this.getRegistrationAddressFromStore(),
|
||||||
city: this.getRegistrationCityFromStore(),
|
city: this.getRegistrationCityFromStore(),
|
||||||
state: this.getRegistrationStateFromStore(),
|
state: this.getRegistrationStateFromStore(),
|
||||||
zip: this.getRegistrationZipFromStore(),
|
zipCode: this.getRegistrationZipFromStore(),
|
||||||
},
|
},
|
||||||
firstName: this.getRegistrationFirstNameFromStore(),
|
firstName: this.getRegistrationFirstNameFromStore(),
|
||||||
lastName: this.getRegistrationLastNameFromStore(),
|
lastName: this.getRegistrationLastNameFromStore(),
|
||||||
emailAddress: this.getEmailFromStore(),
|
emailAddress: this.getEmailFromStore(),
|
||||||
},
|
},
|
||||||
serviceZip: this.getServiceZipFromStore(),
|
serviceZipCode: this.getServiceZipFromStore(),
|
||||||
displayNonServiceableZipAlert: false,
|
displayNonServiceableZipAlert: false,
|
||||||
displayVinNotFoundAlert: false,
|
displayVinNotFoundAlert: false,
|
||||||
displayMatchedDifferentVehicleAlert: false,
|
displayMatchedDifferentVehicleAlert: false,
|
||||||
displayVinLookupByHomeAddressNotAllowedAlert: false,
|
displayVinLookupByHomeAddressNotAllowedAlert: false,
|
||||||
previousCarIdFound: "",
|
previouslyEnteredCarId: "",
|
||||||
customAlertData: {},
|
isSelectedGlassAvailableForVehicle: false,
|
||||||
|
customAlertData: {},
|
||||||
|
showServiceZipField: this.getServiceZipFromStore(),
|
||||||
|
isZipServicable: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -173,65 +179,83 @@ export default {
|
||||||
this.resetWarningsAndErrors();
|
this.resetWarningsAndErrors();
|
||||||
|
|
||||||
// Lookup VIN(s) with the provided address
|
// Lookup VIN(s) with the provided address
|
||||||
const vinLookup = await this.lookupVin(
|
const vinLookup = this.lookupVin(
|
||||||
this.customerQuestions.lastName,
|
this.customerQuestions.lastName,
|
||||||
this.customerQuestions.addressQuestions.streetAddress,
|
this.customerQuestions.addressQuestions.streetAddress,
|
||||||
this.customerQuestions.addressQuestions.zip,
|
this.customerQuestions.addressQuestions.zipCode,
|
||||||
this.customerQuestions.addressQuestions.state
|
this.customerQuestions.addressQuestions.state
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!vinLookup.data.isStatePermissible) {
|
// Verify if the service zip code or registration zip code provided is serviceable
|
||||||
|
const zipValidation = this.serviceZipCode ? this.validateZip(this.serviceZipCode) : this.validateZip(this.customerQuestions.addressQuestions.zipCode);
|
||||||
|
|
||||||
|
const vinLookupResponse = await vinLookup;
|
||||||
|
const zipValidationResponse = await zipValidation;
|
||||||
|
|
||||||
|
if (!vinLookupResponse.data.isStatePermissible) {
|
||||||
// State Restrictions forbid lookup by address
|
// State Restrictions forbid lookup by address
|
||||||
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
|
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate if the original or service zip provided is serviceable
|
// if the neither the registration zip code or service zip code are not serviceable
|
||||||
const zipValidation = this.serviceZip ? await this.validateZip(this.serviceZip) : await this.validateZip(this.customerQuestions.addressQuestions.zip);
|
this.isZipServicable = zipValidationResponse.data.isServiceable;
|
||||||
if (!zipValidation.data.isServiceable) {
|
if (!this.isZipServicable) {
|
||||||
this.displayNonServiceableZipAlert = true;
|
this.displayNonServiceableZipAlert = true;
|
||||||
this.showServiceZipField = true;
|
this.showServiceZipField = true;
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
|
} else if (!this.serviceZipCode) {
|
||||||
|
// if the registration zip code is servicable and nothing was entered for the service zip code
|
||||||
|
// then set the service zip code to the registration zip code
|
||||||
|
this.serviceZipCode = this.customerQuestions.addressQuestions.zipCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const carEntered = store.getters.vehicle;
|
const carEntered = store.getters.vehicle;
|
||||||
const carsFound = vinLookup.data.vinVehicles;
|
const carsFound = vinLookupResponse.data.vinVehicles;
|
||||||
|
|
||||||
if (carsFound.length == 0) {
|
if (carsFound.length == 0) {
|
||||||
// No VINs found
|
// No VINs found
|
||||||
this.displayVinNotFoundAlert = true;
|
this.displayVinNotFoundAlert = true;
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
return;
|
return;
|
||||||
} else if (carsFound.length == 1) {
|
} else if (carsFound.length == 1) {
|
||||||
var carFound = carsFound[0].vehicle;
|
const carFound = carsFound[0].vehicle;
|
||||||
|
this.isCarIdDifferent = carFound.carId !== carEntered.carId;
|
||||||
|
|
||||||
if (carEntered.carId == carFound.carId || carFound.carId == this.previousCarIdFound) {
|
if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) {
|
||||||
// update data
|
|
||||||
this.updateVehicleInfo(carFound.vin, carFound);
|
|
||||||
this.updateCustomerInfo();
|
|
||||||
|
|
||||||
// navigate forward
|
|
||||||
this.navigateForward(carEntered, carsFound);
|
|
||||||
} else {
|
|
||||||
// Display Alert
|
// Display Alert
|
||||||
|
this.previouslyEnteredCarId = carFound.carId;
|
||||||
this.customAlertData.vehicleInfo = carFound;
|
this.customAlertData.vehicleInfo = carFound;
|
||||||
this.displayMatchedDifferentVehicleAlert = true;
|
this.displayMatchedDifferentVehicleAlert = true;
|
||||||
|
|
||||||
|
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(carFound.carId);
|
||||||
|
|
||||||
// Update button "Continue with..."
|
// Update button "Continue with..."
|
||||||
this.$refs.funnelFooter.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model}`);
|
this.$refs.funnelFooter.updateButtonText(`Continue with ${carFound.year} ${carFound.make} ${carFound.model}`);
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
}
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.isZipServicable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.previousCarIdFound = carFound.carId;
|
// update data if the zip or service zip is servicable
|
||||||
|
this.updateVehicleInfo(carsFound[0].vin, carFound);
|
||||||
} else if (vinLookup.data.vinVehicles.length > 1) {
|
|
||||||
this.updateCustomerInfo();
|
this.updateCustomerInfo();
|
||||||
|
|
||||||
|
} else if (carsFound.length > 1) {
|
||||||
|
if (!this.isZipServicable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// navigate forward
|
// update data if the zip or service zip is servicable
|
||||||
this.navigateForward(carEntered, carsFound);
|
this.updateCustomerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.navigateForward(carEntered, carsFound);
|
||||||
},
|
},
|
||||||
resetWarningsAndErrors() {
|
resetWarningsAndErrors() {
|
||||||
this.displayVinNotFoundAlert = false;
|
this.displayVinNotFoundAlert = false;
|
||||||
|
|
@ -239,30 +263,35 @@ export default {
|
||||||
this.displayMatchedDifferentVehicleAlert = false;
|
this.displayMatchedDifferentVehicleAlert = false;
|
||||||
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
|
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
|
||||||
},
|
},
|
||||||
async navigateForward(carEntered, carsFound) {
|
navigateForward(carEntered, carsFound) {
|
||||||
if (carsFound.length == 1) {
|
if (carsFound.length == 1) {
|
||||||
// get the damage options for the car that was found
|
// if a different vehicle is found than the one entered and the selected glass
|
||||||
const carFound = carsFound[0].vehicle;
|
// is not available for that vehicle
|
||||||
const glassOptions = await baseMixin.methods.dispatchStoreAction(
|
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||||
storeActions.GET_DAMAGE_OPTIONS,
|
this.$router.navigateAfterSave(
|
||||||
{ carId: carFound.carId }
|
// then navigate back to "vehicle-damage", and display vehicle changed alert
|
||||||
);
|
// on that page
|
||||||
|
this.navigationScenarios.CONTINUING_WITH_DIFFERENT_GLASS,
|
||||||
// if the car entered is the same as the car found OR the glass options for the found car match the users damage selections
|
this.$route, {}, {
|
||||||
if (carEntered.carId == carFound.carId || isGlassAvailableForCarId(carFound.carId)) {
|
displayVehicleChangeAlert: true
|
||||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
}, {}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
// if not then navigate to the "vehicle-damage" page
|
// otherwise
|
||||||
this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD, this.$route, {}, { displayVehicleChangeAlert: true }, {});
|
this.$refs.loadingModal.showModal();
|
||||||
}
|
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||||
|
}
|
||||||
} else if (carsFound.length > 1) {
|
} else if (carsFound.length > 1) {
|
||||||
// if multiple cars were found
|
// if multiple cars were found
|
||||||
if (carsFound.find(car => car.carId === carEntered.carId)) {
|
if (carsFound.find(car => car.carId === carEntered.carId)) {
|
||||||
// and one of them matches the car id entered
|
// and one of them matches the car id entered
|
||||||
|
this.$refs.loadingModal.showModal();
|
||||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||||
} else {
|
} else {
|
||||||
// and there is no match, navigate to "address-vehicle" page
|
// and there is no match, navigate to "address-vehicles" page
|
||||||
this.$router.navigateAfterSave(this.navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES, this.$route, {}, {}, carsFound);
|
this.$router.navigateAfterSave(this.navigationScenarios.CONTINUING_WITH_MULTIPLE_VEHICLES,
|
||||||
|
this.$route, {}, {},
|
||||||
|
carsFound);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -302,29 +331,29 @@ export default {
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.customerQuestions.addressQuestions.zipCode);
|
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.customerQuestions.addressQuestions.zipCode);
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, this.customerQuestions.firstName);
|
store.commit(storeMutations.UPDATE_REGISTRATION_FIRST_NAME, this.customerQuestions.firstName);
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, this.customerQuestions.lastName);
|
store.commit(storeMutations.UPDATE_REGISTRATION_LAST_NAME, this.customerQuestions.lastName);
|
||||||
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZip);
|
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZipCode);
|
||||||
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.customerQuestions.email);
|
store.commit(storeMutations.UPDATE_CUSTOMER_EMAIL_ADDRESS, this.customerQuestions.emailAddress);
|
||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
AlertNonServiceableZipHeader(){
|
AlertNonServiceableZipHeader(){
|
||||||
let zip = this.serviceZip ? this.serviceZip : this.customerQuestions.addressQuestions.zip;
|
const zipCode = this.serviceZipCode ? this.serviceZipCode : this.customerQuestions.addressQuestions.zipCode;
|
||||||
let text = this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", zip);
|
const text = this.getCmsContent("AlertNonServiceableZipWidget", "HeadlineText").replaceAll("{custom:serviceZip}", zipCode);
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
AlertNonServiceableZipBody(){
|
AlertNonServiceableZipBody(){
|
||||||
return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText");
|
return this.getCmsContent("AlertNonServiceableZipWidget", "BodyText");
|
||||||
},
|
},
|
||||||
AlertMatchedDifferentVehicleHeader(){
|
AlertMatchedDifferentVehicleHeader(){
|
||||||
let text = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:glassText}", getDamageString());
|
const text = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "HeadlineText").replaceAll("{custom:glassText}", getDamageString());
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
AlertMatchedDifferentVehicleBody(){
|
AlertMatchedDifferentVehicleBody(){
|
||||||
let content = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText");
|
let content = this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText");
|
||||||
content = content.replaceAll("{custom:glassText}", getDamageString());
|
content = content.replaceAll("{custom:glassText}", getDamageString());
|
||||||
let vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
|
||||||
let vinYmmExpected = `${store.getters.vehicle.year} ${store.getters.vehicle.make} ${store.getters.vehicle.model}`;
|
const vinYmmExpected = `${store.getters.vehicle.year} ${store.getters.vehicle.make} ${store.getters.vehicle.model}`;
|
||||||
|
|
||||||
content = content.replaceAll("{custom:vinYmmFound}", vinYmmFound);
|
content = content.replaceAll("{custom:vinYmmFound}", vinYmmFound);
|
||||||
content = content.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
|
content = content.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
|
||||||
|
|
@ -335,20 +364,27 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
customerQuestions: {
|
customerQuestions: {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
// if they modify one of the lookup fields (address, city, state, zip, 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.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
|
this.$refs.funnelFooter.updateButtonText(this.getCmsContent("FunnelFooterWidget", "ForwardButtonText"));
|
||||||
this.showServiceZipField = false;
|
this.showServiceZipField = false;
|
||||||
this.resetWarningsAndErrors();
|
this.resetWarningsAndErrors();
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
},
|
},
|
||||||
serviceZip: {
|
serviceZipCode: {
|
||||||
handler(newValue) {
|
handler(newValue) {
|
||||||
// if they modify the service zip, then hide the error message”
|
// if they modify the service zip code, then hide the error message”
|
||||||
this.displayNonServiceableZipAlert = false;
|
this.displayNonServiceableZipAlert = false;
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
showServiceZipField: {
|
||||||
|
handler(newValue) {
|
||||||
|
// if the Service Zip Code field is ever hidden, clear out it's value
|
||||||
|
if (!newValue) {
|
||||||
|
this.serviceZipCode = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
|
|
@ -358,6 +394,7 @@ export default {
|
||||||
customerQuestions,
|
customerQuestions,
|
||||||
textboxQuestion,
|
textboxQuestion,
|
||||||
alert,
|
alert,
|
||||||
|
loadingModal,
|
||||||
Form
|
Form
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
<dropdownQuestion cmsWidgetName="StateQuestionWidget" v-model="addressModel.state" ref="state" inputId="8fdf9dc2e13e430eb57529499dceb3eb" :options="stateOptions" disableAutoFill validationRules="state-required" />
|
<dropdownQuestion cmsWidgetName="StateQuestionWidget" v-model="addressModel.state" ref="state" inputId="8fdf9dc2e13e430eb57529499dceb3eb" :options="stateOptions" disableAutoFill validationRules="state-required" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion cmsWidgetName="ZipQuestionWidget" v-model="addressModel.zip" ref="zip" inputId="01a9a1c2de0b4c9da8e023c9ae3be498" mask="#####" disableAutoFill validationRules="zip-required|zip-format"/>
|
<textboxQuestion cmsWidgetName="ZipQuestionWidget" v-model="addressModel.zipCode" ref="zipCode" inputId="01a9a1c2de0b4c9da8e023c9ae3be498" mask="#####" disableAutoFill validationRules="zip-code-required|zip-code-format"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
|
|
@ -48,8 +48,8 @@ import { errorMessages } from "@/constants/error-messages";
|
||||||
defineRule("street-address-required", required(errorMessages.STREET_ADDRESS_REQUIRED));
|
defineRule("street-address-required", required(errorMessages.STREET_ADDRESS_REQUIRED));
|
||||||
defineRule("city-required", required(errorMessages.CITY_REQUIRED));
|
defineRule("city-required", required(errorMessages.CITY_REQUIRED));
|
||||||
defineRule("state-required", required(errorMessages.STATE_REQUIRED));
|
defineRule("state-required", required(errorMessages.STATE_REQUIRED));
|
||||||
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
|
defineRule("zip-code-required", required(errorMessages.ZIP_REQUIRED));
|
||||||
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.ZIP_FORMAT));
|
defineRule("zip-code-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.ZIP_FORMAT));
|
||||||
|
|
||||||
export default ({
|
export default ({
|
||||||
name: "address-questions",
|
name: "address-questions",
|
||||||
|
|
@ -61,7 +61,7 @@ export default ({
|
||||||
streetAddress: "",
|
streetAddress: "",
|
||||||
city: "",
|
city: "",
|
||||||
state: "",
|
state: "",
|
||||||
zip: "",
|
zipCode: "",
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
|
|
@ -146,6 +146,15 @@ export default ({
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
setupAddressLookup() {
|
setupAddressLookup() {
|
||||||
|
|
||||||
|
if (this.addressModel.streetAddress !== null &
|
||||||
|
this.addressModel.city !== null &
|
||||||
|
this.addressModel.state !== null &
|
||||||
|
this.addressModel.zipCode !== null) {
|
||||||
|
|
||||||
|
this.showAddressFields = true;
|
||||||
|
}
|
||||||
|
|
||||||
const addressField1 = document.getElementById("autocomplete");
|
const addressField1 = document.getElementById("autocomplete");
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
|
|
@ -166,7 +175,7 @@ export default ({
|
||||||
// Standard place_changed event handling
|
// Standard place_changed event handling
|
||||||
autocomplete.addListener('place_changed', fillInAddress);
|
autocomplete.addListener('place_changed', fillInAddress);
|
||||||
|
|
||||||
addressField1.onblur = function() {
|
addressField1.onchange = function() {
|
||||||
const hover = document.querySelector(".pac-container .pac-item:hover");
|
const hover = document.querySelector(".pac-container .pac-item:hover");
|
||||||
// if an item has been clicked, do nothing, otherwise get first solution and use Geocoder to get the place
|
// if an item has been clicked, do nothing, otherwise get first solution and use Geocoder to get the place
|
||||||
if (hover === null) {
|
if (hover === null) {
|
||||||
|
|
@ -187,7 +196,7 @@ export default ({
|
||||||
else {
|
else {
|
||||||
self.addressModel.city = "";
|
self.addressModel.city = "";
|
||||||
self.addressModel.state = "";
|
self.addressModel.state = "";
|
||||||
self.addressModel.zip = "";
|
self.addressModel.zipCode = "";
|
||||||
self.showAddressFields = true;
|
self.showAddressFields = true;
|
||||||
self.displayVerificationWarning = false;
|
self.displayVerificationWarning = false;
|
||||||
self.displayNoMatchWarning = true;
|
self.displayNoMatchWarning = true;
|
||||||
|
|
@ -225,7 +234,7 @@ export default ({
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case "postal_code": {
|
case "postal_code": {
|
||||||
self.addressModel.zip = component.long_name;
|
self.addressModel.zipCode = component.long_name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ export default ({
|
||||||
streetAddress: "",
|
streetAddress: "",
|
||||||
city: "",
|
city: "",
|
||||||
state: "",
|
state: "",
|
||||||
zip: "",
|
zipCode: "",
|
||||||
},
|
},
|
||||||
firstName: "",
|
firstName: "",
|
||||||
lastName: "",
|
lastName: "",
|
||||||
|
|
|
||||||
|
|
@ -5,29 +5,34 @@
|
||||||
ref="theForm"
|
ref="theForm"
|
||||||
v-slot="{ meta }"
|
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" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" />
|
<vehicleBanner cmsWidgetName="VehicleBannerWidget" />
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<buttonQuestion
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
cmsWidgetName="VinLookupMethod"
|
<alert
|
||||||
class="button-question-overflow"
|
class="vinLookupMethodHeading"
|
||||||
:questionText="questionText"
|
v-model="customAlertData"
|
||||||
:answers="answersFromCms"
|
alertClass=""
|
||||||
groupName="vinLookupMethodOption"
|
cmsWidgetName="AlertVinLookupQuestion"
|
||||||
buttonType="listButton"
|
|
||||||
v-model="selectedValues"
|
|
||||||
isRequired
|
|
||||||
validationRules="option-required"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<funnel-footer
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
:isForwardActionDisabled="!meta.valid"
|
|
||||||
@isDisabled="!meta.valid"
|
|
||||||
@back-clicked="backButtonAction"
|
|
||||||
@ForwardClicked="forwardButtonAction"
|
|
||||||
/>
|
/>
|
||||||
|
<buttonQuestion
|
||||||
|
cmsWidgetName="VinLookupMethod"
|
||||||
|
: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>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -39,6 +44,7 @@ import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
|
||||||
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||||
import buttonQuestion from "@/common-components/button-question/button-question";
|
import buttonQuestion from "@/common-components/button-question/button-question";
|
||||||
|
import alert from "@/ux-components/alert/alert";
|
||||||
//Supporting Files
|
//Supporting Files
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
|
@ -126,6 +132,18 @@ export default {
|
||||||
funnelFooter,
|
funnelFooter,
|
||||||
buttonQuestion,
|
buttonQuestion,
|
||||||
Form,
|
Form,
|
||||||
|
alert,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.vinLookupMethodHeading p {
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 500;
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
|
div .current_car_info-text {
|
||||||
|
padding-bottom: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1,17 +1,18 @@
|
||||||
// Components
|
// 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
|
// Supporting Files
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
||||||
|
import * as navigateToHeritage from "@/helpers/heritage-integration/navigation-helper";
|
||||||
import baseMixin from "@/mixins/base-mixin";
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { shallowMount, flushPromises } from "@vue/test-utils";
|
import { shallowMount, flushPromises } from "@vue/test-utils";
|
||||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
|
||||||
import { storeMutations } from "@/constants/store-mutations";
|
|
||||||
import store from "@/store";
|
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.
|
// Mock our module for promises.
|
||||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
|
|
@ -29,25 +30,15 @@ jest.mock("@/store", () => ({
|
||||||
dispatch: jest.fn(),
|
dispatch: jest.fn(),
|
||||||
getters: {
|
getters: {
|
||||||
order: {
|
order: {
|
||||||
customer: {
|
customer: { emailAddress: "test@test.com"},
|
||||||
emailAddress: "test@test.com"
|
serviceLocation: {zip: "11111"},
|
||||||
},
|
|
||||||
serviceLocation: {
|
|
||||||
zipCode: "43443"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
vehicle: {
|
vehicle: {
|
||||||
carId: "C00000000",
|
carId: "TESTID",
|
||||||
image: "test.jpg",
|
|
||||||
payment: {
|
|
||||||
insuranceCoverage: {
|
|
||||||
isVerified: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
registration: {
|
registration: {
|
||||||
licensePlate: "HWV4445",
|
licensePlate: "TESTPLATE",
|
||||||
zipCode: "43224"
|
zipCode: "12345",
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
eventBusItem: jest.fn(),
|
eventBusItem: jest.fn(),
|
||||||
damage: {
|
damage: {
|
||||||
|
|
@ -62,7 +53,7 @@ describe("license-plate-lookup.vue", () => {
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
vehicleDamage.beforeRouteEnter.call(
|
licensePlateLookup.beforeRouteEnter.call(
|
||||||
wrapper.vm,
|
wrapper.vm,
|
||||||
{ query: { fmgPage: "license-plate-lookup" } },
|
{ query: { fmgPage: "license-plate-lookup" } },
|
||||||
undefined,
|
undefined,
|
||||||
|
|
@ -84,7 +75,7 @@ describe("license-plate-lookup.vue", () => {
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
vehicleDamage.beforeRouteEnter.call(
|
licensePlateLookup.beforeRouteEnter.call(
|
||||||
wrapper.vm,
|
wrapper.vm,
|
||||||
{ query: { fmgPage: "license-plate-lookup" } },
|
{ query: { fmgPage: "license-plate-lookup" } },
|
||||||
undefined,
|
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({
|
function setupMocks({
|
||||||
pageHeaderWidgetHeaderText = {},
|
pageHeaderWidgetHeaderText = {},
|
||||||
|
|
@ -106,12 +431,8 @@ function setupMocks({
|
||||||
router: {
|
router: {
|
||||||
navigate: jest.fn(),
|
navigate: jest.fn(),
|
||||||
},
|
},
|
||||||
store: {
|
licensePlate: "TESTPLATE",
|
||||||
getters: {
|
registrationZip: "12345"
|
||||||
vehicle: {},
|
|
||||||
payment: { insuranceCoverage: { isVerified: false } },
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}) {
|
}) {
|
||||||
//Mock api responses
|
//Mock api responses
|
||||||
|
|
@ -139,7 +460,7 @@ function setupMocks({
|
||||||
const mountOptions = getMountOptions(mountOptionsMockData);
|
const mountOptions = getMountOptions(mountOptionsMockData);
|
||||||
mountOptions['attachTo'] = document.body; // append wrapper to document.body to test DOM methods
|
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;
|
wrapper.vm.setCmsContent = baseMixin.methods.setCmsContent;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,108 +1,41 @@
|
||||||
<template>
|
<template>
|
||||||
<Form
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
@submit="onSubmit"
|
<div class="page-container-grouped-styles">
|
||||||
@invalid-submit="onInvalidSubmit"
|
<loadingModal ref="loadingModal"/>
|
||||||
ref="theForm"
|
|
||||||
v-slot="{ meta }"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5"
|
|
||||||
>
|
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<vehicleBanner
|
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
|
||||||
:displayGenericVehicleImage="false"
|
|
||||||
/>
|
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<div class="row my-2">
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
<div class="col">
|
<div class="row my-2">
|
||||||
<textboxQuestion
|
<div class="col">
|
||||||
cmsWidgetName="LicensePlateNumber"
|
<textboxQuestion cmsWidgetName="LicensePlateNumber" v-model="licensePlate" isRequired inputId="license_plate" validationRules="license-plate-required" />
|
||||||
v-model="licensePlate"
|
</div>
|
||||||
isRequired
|
|
||||||
inputId="license_plate"
|
|
||||||
validationRules="license-plate-required"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row my-2">
|
||||||
<div class="row my-2">
|
<div class="col">
|
||||||
<div class="col">
|
<textboxQuestion cmsWidgetName="RegistrationZip" v-model="registrationZip" inputId="zip" mask="#####" validationRules="zip-required" />
|
||||||
<textboxQuestion
|
</div>
|
||||||
cmsWidgetName="RegistrationZip"
|
|
||||||
v-model="registrationZip"
|
|
||||||
inputId="zip"
|
|
||||||
mask="#####"
|
|
||||||
validationRules="zip-required"
|
|
||||||
/>
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="RegistrationZip"
|
|
||||||
v-model="registrationZip"
|
|
||||||
isRequired
|
|
||||||
inputId="zip"
|
|
||||||
mask="#####"
|
|
||||||
validationRules="zip-required"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row my-2">
|
||||||
<div class="row my-2">
|
<div class="col">
|
||||||
<div class="col">
|
<textboxQuestion cmsWidgetName="EmailAddress" v-model="email" inputId="email" validationRules="email-address-required|email-address-format" />
|
||||||
<textboxQuestion
|
</div>
|
||||||
cmsWidgetName="EmailAddress"
|
|
||||||
v-model="email"
|
|
||||||
inputId="email"
|
|
||||||
validationRules="email-address-required|email-address-format"
|
|
||||||
/>
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="EmailAddress"
|
|
||||||
v-model="email"
|
|
||||||
isRequired
|
|
||||||
inputId="email"
|
|
||||||
validationRules="email-address-required|email-address-format"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<alert class="my-3" :manualHeadline="NoServiceZipHeader" :manualCopy="NoServiceZipBody" v-if="!isRegistrationZipServicable && isVinValid && !isCarIdDifferent" alertClass="alert-danger" />
|
||||||
<alert
|
<div class="row my-2">
|
||||||
class="my-3"
|
<div class="col">
|
||||||
:manualHeadline="NoServiceZipHeader"
|
<textboxQuestion v-if="!isRegistrationZipServicable" cmsWidgetName="ServiceZip" v-model="serviceZip" inputId="serviceZip" validationRules="zip-required" />
|
||||||
:manualCopy="NoServiceZipBody"
|
</div>
|
||||||
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>
|
||||||
|
<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>
|
||||||
<alert
|
|
||||||
class="my-3"
|
|
||||||
cmsWidgetName="NoMatchAlertWidget"
|
|
||||||
v-if="!isVinValid"
|
|
||||||
alertClass="alert-danger"
|
|
||||||
/>
|
|
||||||
<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>
|
</template>
|
||||||
|
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
||||||
|
|
@ -111,29 +44,47 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||||
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
||||||
|
import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import {
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
fetchCmsContentForPage
|
||||||
|
} from "@/helpers/cms-content-helper";
|
||||||
|
import {
|
||||||
|
settleAllPromises
|
||||||
|
} from "@/helpers/layout-helper";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import {
|
||||||
import { storeMutations } from "@/constants/store-mutations";
|
storeActions
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
} from "@/constants/store-actions";
|
||||||
|
import {
|
||||||
|
storeMutations
|
||||||
|
} from "@/constants/store-mutations";
|
||||||
|
import {
|
||||||
|
errorMessages
|
||||||
|
} from "@/constants/error-messages";
|
||||||
|
import {
|
||||||
|
navigateAfterSaveToHeritageFunnel
|
||||||
|
} from "@/helpers/heritage-integration/navigation-helper";
|
||||||
import {
|
import {
|
||||||
getDamageString,
|
getDamageString,
|
||||||
isGlassAvailableForCarId,
|
isGlassAvailableForCarId,
|
||||||
} from "@/helpers/damage-helper";
|
} from "@/helpers/damage-helper";
|
||||||
import { required, regex } from "@/helpers/validation-rules";
|
import {
|
||||||
import { Form, defineRule } from "vee-validate";
|
required,
|
||||||
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
regex,
|
||||||
|
} from "@/helpers/validation-rules";
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
defineRule,
|
||||||
|
} from "vee-validate";
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
// DEFINE VALIDATION RULES
|
||||||
defineRule(
|
defineRule(
|
||||||
"license-plate-required",
|
"license-plate-required",
|
||||||
required(errorMessages.LICENSE_PLATE_REQUIRED)
|
required(errorMessages.LICENSE_PLATE_REQUIRED)
|
||||||
);
|
);
|
||||||
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
|
defineRule("zip-required", required(errorMessages.REGISTRATION_ZIP_REQUIRED));
|
||||||
defineRule(
|
defineRule(
|
||||||
"email-address-required",
|
"email-address-required",
|
||||||
required(errorMessages.EMAIL_ADDRESS_REQUIRED)
|
required(errorMessages.EMAIL_ADDRESS_REQUIRED)
|
||||||
|
|
@ -145,7 +96,6 @@ defineRule(
|
||||||
errorMessages.EMAIL_ADDRESS_FORMAT
|
errorMessages.EMAIL_ADDRESS_FORMAT
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "license-plate-lookup",
|
name: "license-plate-lookup",
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
@ -159,9 +109,7 @@ export default {
|
||||||
promise: cmsContentPromise,
|
promise: cmsContentPromise,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
// 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);
|
||||||
|
|
@ -182,6 +130,7 @@ export default {
|
||||||
previouslyEnteredCarId: "",
|
previouslyEnteredCarId: "",
|
||||||
customAlertData: {},
|
customAlertData: {},
|
||||||
isSelectedGlassAvailableForVehicle: true,
|
isSelectedGlassAvailableForVehicle: true,
|
||||||
|
zipToDisplay: this.getRegistrationZipFromStore(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -193,7 +142,6 @@ export default {
|
||||||
"MatchedDifferentVehicleAlertWidget",
|
"MatchedDifferentVehicleAlertWidget",
|
||||||
"HeadlineText"
|
"HeadlineText"
|
||||||
).replaceAll("{custom:damage}", getDamageString());
|
).replaceAll("{custom:damage}", getDamageString());
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
MatchedDifferentVehicleAlertBody() {
|
MatchedDifferentVehicleAlertBody() {
|
||||||
|
|
@ -214,15 +162,13 @@ export default {
|
||||||
"{custom:plateLookupModel}",
|
"{custom:plateLookupModel}",
|
||||||
this.customAlertData?.vehicleInfo?.model
|
this.customAlertData?.vehicleInfo?.model
|
||||||
);
|
);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
NoServiceZipHeader() {
|
NoServiceZipHeader() {
|
||||||
let text = this.getCmsContent(
|
let text = this.getCmsContent(
|
||||||
"NoServiceZipWidget",
|
"NoServiceZipWidget",
|
||||||
"HeadlineText"
|
"HeadlineText"
|
||||||
).replaceAll("{custom:zip}", this.registrationZip);
|
).replaceAll("{custom:zip}", this.zipToDisplay);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
NoServiceZipBody() {
|
NoServiceZipBody() {
|
||||||
|
|
@ -259,24 +205,24 @@ export default {
|
||||||
getEmailFromStore() {
|
getEmailFromStore() {
|
||||||
return store.getters.order.customer.emailAddress;
|
return store.getters.order.customer.emailAddress;
|
||||||
},
|
},
|
||||||
getServiceZipFromStore(){
|
getServiceZipFromStore() {
|
||||||
return store.getters.order.serviceLocation.zipCode
|
return store.getters.order.serviceLocation.zip;
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
const zipValidation = this.serviceZip
|
const zipValidation = this.serviceZip ?
|
||||||
? await this.validateZip(this.serviceZip)
|
await this.validateZip(this.serviceZip) :
|
||||||
: await this.validateZip(this.registrationZip);
|
await this.validateZip(this.registrationZip);
|
||||||
if (!zipValidation.data.isServiceable) {
|
if (!zipValidation.data.isServiceable) {
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
this.isVinValid = true;
|
this.isVinValid = true;
|
||||||
this.isRegistrationZipServicable = false;
|
this.isRegistrationZipServicable = false;
|
||||||
this.isCarIdDifferent = false;
|
this.isCarIdDifferent = false;
|
||||||
|
this.zipToDisplay = this.serviceZip ? this.serviceZip : this.registrationZip;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const vinLookup = await this.lookupVin(
|
const vinLookup = await this.lookupVin(
|
||||||
this.licensePlate,
|
this.licensePlate,
|
||||||
zipValidation.data.state
|
zipValidation.data.state
|
||||||
|
|
@ -286,7 +232,6 @@ export default {
|
||||||
this.isCarIdDifferent = false;
|
this.isCarIdDifferent = false;
|
||||||
return;
|
return;
|
||||||
});
|
});
|
||||||
|
|
||||||
this.isCarIdDifferent =
|
this.isCarIdDifferent =
|
||||||
vinLookup.data.vehicle.carId !== store.getters.vehicle.carId;
|
vinLookup.data.vehicle.carId !== store.getters.vehicle.carId;
|
||||||
|
|
||||||
|
|
@ -311,33 +256,21 @@ export default {
|
||||||
vinLookup.data.vehicle,
|
vinLookup.data.vehicle,
|
||||||
zipValidation.data.state
|
zipValidation.data.state
|
||||||
);
|
);
|
||||||
|
|
||||||
const partsData = await baseMixin.methods.dispatchStoreAction(
|
this.navigateForward();
|
||||||
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) {
|
navigateForward() {
|
||||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||||
this.$router.navigateAfterSave(
|
this.$router.navigateAfterSave(
|
||||||
this.navigationScenarios.CLICKED_FORWARD,
|
this.navigationScenarios.CLICKED_FORWARD,
|
||||||
this.$route,
|
this.$route,
|
||||||
{},
|
{},
|
||||||
{ displayVehicleChangeAlert: true },
|
{ displayVehicleChangeAlert: true },
|
||||||
partsData.data
|
{}
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
this.$refs.loadingModal.showModal();
|
||||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -355,7 +288,7 @@ export default {
|
||||||
},
|
},
|
||||||
updateCustomerInfo(vin, vehicleInfo, registrationState) {
|
updateCustomerInfo(vin, vehicleInfo, registrationState) {
|
||||||
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
|
||||||
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
}
|
}
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
|
store.commit(storeMutations.UPDATE_VEHICLE_VIN, vin);
|
||||||
store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);
|
store.commit(storeMutations.UPDATE_YEAR, vehicleInfo.year);
|
||||||
|
|
@ -363,11 +296,11 @@ export default {
|
||||||
store.commit(storeMutations.UPDATE_MODEL, vehicleInfo.model);
|
store.commit(storeMutations.UPDATE_MODEL, vehicleInfo.model);
|
||||||
store.commit(storeMutations.UPDATE_STYLE, vehicleInfo.style);
|
store.commit(storeMutations.UPDATE_STYLE, vehicleInfo.style);
|
||||||
store.commit(storeMutations.UPDATE_CAR_ID, vehicleInfo.carId);
|
store.commit(storeMutations.UPDATE_CAR_ID, vehicleInfo.carId);
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY,vehicleInfo.category);
|
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, vehicleInfo.category);
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL,vehicleInfo.imageUrl);
|
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_VIF_NUMBER, vehicleInfo.imageVifNumber);
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR,vehicleInfo.imageColor);
|
store.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, vehicleInfo.imageVifColor);
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE,this.licensePlate);
|
store.commit(storeMutations.UPDATE_REGISTRATION_LICENSE_PLATE, this.licensePlate);
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState);
|
store.commit(storeMutations.UPDATE_REGISTRATION_STATE, registrationState);
|
||||||
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.registrationZip);
|
store.commit(storeMutations.UPDATE_REGISTRATION_ZIP_CODE, this.registrationZip);
|
||||||
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZip);
|
store.commit(storeMutations.UPDATE_SERVICE_LOCATION_ZIP_CODE, this.serviceZip);
|
||||||
|
|
@ -399,6 +332,7 @@ export default {
|
||||||
textboxQuestion,
|
textboxQuestion,
|
||||||
alert,
|
alert,
|
||||||
funnelFooter,
|
funnelFooter,
|
||||||
|
loadingModal,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -1,12 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall">
|
<div class="page-container-grouped-styles">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage=false />
|
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage=false />
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<h1>Part Questions Page Placeholder</h1>
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
<funnel-footer
|
<h1>Part Questions Page Placeholder</h1>
|
||||||
cmsWidgetName="FunnelFooterWidget" @back-clicked="backButtonAction"
|
<funnel-footer
|
||||||
/>
|
cmsWidgetName="FunnelFooterWidget" @back-clicked="backButtonAction"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,61 +5,63 @@
|
||||||
ref="theForm"
|
ref="theForm"
|
||||||
v-slot="{ meta }"
|
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" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage=false />
|
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage=false />
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<alert
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
ref="vehicleChangeAlert"
|
<alert
|
||||||
class="mt-5 mb-0"
|
ref="vehicleChangeAlert"
|
||||||
cmsWidgetName="VehicleChangeAlert"
|
class="mt-5 mb-0"
|
||||||
v-show="shouldDisplayVehicleChangeAlert"
|
cmsWidgetName="VehicleChangeAlert"
|
||||||
alertClass="alert-warning"
|
v-show="shouldDisplayVehicleChangeAlert"
|
||||||
:isDismissible="false"
|
alertClass="alert-warning"
|
||||||
/>
|
:isDismissible="false"
|
||||||
<damageLocationQuestion
|
/>
|
||||||
ref="damageLocation"
|
<damageLocationQuestion
|
||||||
cmsWidgetName="DamageLocationQuestion"
|
ref="damageLocation"
|
||||||
v-model="selectedDamageLocations"
|
cmsWidgetName="DamageLocationQuestion"
|
||||||
groupName="DamageLocationQuestion"
|
v-model="selectedDamageLocations"
|
||||||
/>
|
groupName="DamageLocationQuestion"
|
||||||
<windshieldOptions
|
/>
|
||||||
ref="windshieldOptions"
|
<windshieldOptions
|
||||||
v-model="selectedWindshieldOptions"
|
ref="windshieldOptions"
|
||||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
v-model="selectedWindshieldOptions"
|
||||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||||
:selectedDamageLocations="selectedDamageLocations"
|
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||||
/>
|
:selectedDamageLocations="selectedDamageLocations"
|
||||||
<alert
|
/>
|
||||||
class="my-3"
|
<alert
|
||||||
cmsWidgetName="HasReplacementConflict"
|
class="my-3"
|
||||||
v-show="hasRepairReplaceConflict"
|
cmsWidgetName="HasReplacementConflict"
|
||||||
alertClass="alert-danger"
|
v-show="hasRepairReplaceConflict"
|
||||||
:isDismissible="false"
|
alertClass="alert-danger"
|
||||||
/>
|
:isDismissible="false"
|
||||||
<sideDoorOptions
|
/>
|
||||||
ref="sideDoorOptions"
|
<sideDoorOptions
|
||||||
cmsWidgetName="SideDoorSideQuestion"
|
ref="sideDoorOptions"
|
||||||
groupName="SideDoorSideQuestion"
|
cmsWidgetName="SideDoorSideQuestion"
|
||||||
v-model="sideDoorOptionsData"
|
groupName="SideDoorSideQuestion"
|
||||||
v-show="!hasRepairReplaceConflict"
|
v-model="sideDoorOptionsData"
|
||||||
:selectedDamageLocations="selectedDamageLocations"
|
v-show="!hasRepairReplaceConflict"
|
||||||
/>
|
:selectedDamageLocations="selectedDamageLocations"
|
||||||
<replaceOptionsQuestion
|
/>
|
||||||
ref="backGlassOptions"
|
<replaceOptionsQuestion
|
||||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
ref="backGlassOptions"
|
||||||
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||||
v-model="selectedRearReplaceOptions"
|
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
||||||
groupName="BackGlassReplaceOptionsQuestion"
|
v-model="selectedRearReplaceOptions"
|
||||||
validationRules="replace-options-required"
|
groupName="BackGlassReplaceOptionsQuestion"
|
||||||
/>
|
validationRules="replace-options-required"
|
||||||
<funnel-footer
|
/>
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
<funnel-footer
|
||||||
:isForwardActionDisabled="!meta.valid"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
:isBackButtonHidden=shouldHideBackButton
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
:isBackButtonHidden=shouldHideBackButton
|
||||||
@ForwardClicked="forwardButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
/>
|
@ForwardClicked="forwardButtonAction"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<buttonQuestion
|
<buttonQuestion
|
||||||
class="radioQuestion"
|
class="radioQuestion"
|
||||||
isOverflowScrollable
|
isOverflowScrollable
|
||||||
selectingInitiatesLoad
|
selectingInitiatesLoad
|
||||||
:questionText="questionText"
|
:questionText="questionText"
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container-fluid shadow rounded-3 p-0 position-relative make-tall">
|
<div class="page-container-grouped-styles">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<div class="select-car">
|
<div class="select-car">
|
||||||
<div class="select-car-form rounded text-center">
|
<div class="select-car-form rounded text-center">
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
backButtonAccessibleText="Change Vehicle Year"
|
backButtonAccessibleText="Change Vehicle Year"
|
||||||
@click-event="backButtonAction"
|
@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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container-fluid shadow rounded-3 p-0 position-relative">
|
<div class="page-container-grouped-styles">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<div class="select-car">
|
<div class="select-car">
|
||||||
<div class="select-car-form rounded text-center">
|
<div class="select-car-form rounded text-center">
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
backButtonAccessibleText="Change Vehicle Make"
|
backButtonAccessibleText="Change Vehicle Make"
|
||||||
@click-event="backButtonAction"
|
@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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,38 @@
|
||||||
<template>
|
<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" />
|
<funnelHeader ref="funnelHeader" cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<vehicleBanner ref="vehicleBanner" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
<vehicleBanner ref="vehicleBanner" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
||||||
<funnelSubHeader ref="funnelSubHeader" cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader ref="funnelSubHeader" cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<div class="container-fluid prevent-squish my-5">
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
<div class="row">
|
<div class="container-fluid prevent-squish my-5">
|
||||||
<div class="col">
|
<div class="row">
|
||||||
<alert
|
<div class="col">
|
||||||
class="rounded border-0 shadow-sm"
|
<alert
|
||||||
alertClass="alert-warning"
|
class="rounded border-0 shadow-sm"
|
||||||
cmsWidgetName="AlertWidget"
|
alertClass="alert-warning"
|
||||||
:isDismissible="false"
|
cmsWidgetName="AlertWidget"
|
||||||
/>
|
:isDismissible="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div v-for="(item, i) in PartsForQuestions" :key="i">
|
<div v-for="(item, i) in PartsForQuestions" :key="i">
|
||||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<hr v-if="i > 0" />
|
<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>
|
</div>
|
||||||
|
<funnelFooter cmsWidgetName="FunnelFooterWidget" ref="funnelFooter" @back-clicked="backButtonAction" @ForwardClicked="forwardButtonAction" />
|
||||||
<glassPartQuestion
|
|
||||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
|
||||||
v-model="glassParts[item.glassLocation + '-' + item.glassName]"
|
|
||||||
:glassLocation="item.glassLocation"
|
|
||||||
:glassName="item.glassName"
|
|
||||||
:colorAnswers="item.colorAnswers"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<funnelFooter cmsWidgetName="FunnelFooterWidget" ref="funnelFooter" @back-clicked="backButtonAction" @ForwardClicked="forwardButtonAction" />
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container-fluid shadow rounded-3 p-0 position-relative">
|
<div class="page-container-grouped-styles">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<div class="select-car">
|
<div class="select-car">
|
||||||
<div class="select-car-form rounded text-center">
|
<div class="select-car-form rounded text-center">
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
backButtonAccessibleText="Change Vehicle Model"
|
backButtonAccessibleText="Change Vehicle Model"
|
||||||
@click-event="backButtonAction"
|
@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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container-fluid shadow rounded-3 p-0 position-relative">
|
<div class="page-container-grouped-styles">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<div class="select-car">
|
<div class="select-car">
|
||||||
<div class="select-car-form rounded text-center">
|
<div class="select-car-form rounded text-center">
|
||||||
<vehicleBanner cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage />
|
<vehicleBanner cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage />
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -5,109 +5,118 @@
|
||||||
ref="theForm"
|
ref="theForm"
|
||||||
v-slot="{ meta }"
|
v-slot="{ meta }"
|
||||||
>
|
>
|
||||||
<div
|
<div class="page-container-grouped-styles">
|
||||||
class="container-fluid shadow rounded-3 p-2 position-relative make-tall px-5"
|
<loadingModal ref="loadingModal"/>
|
||||||
>
|
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="false"
|
:displayGenericVehicleImage="false"
|
||||||
/>
|
/>
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
<div class="row my-2">
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
<div class="col">
|
<div class="row my-2">
|
||||||
<textboxQuestion
|
<div class="col">
|
||||||
cmsWidgetName="VinNumber"
|
<textboxQuestion
|
||||||
v-model="vin"
|
cmsWidgetName="VinNumber"
|
||||||
inputId="vin"
|
v-model="vin"
|
||||||
isRequired
|
inputId="vin"
|
||||||
disableAutoFill
|
isRequired
|
||||||
validationRules="vin-required|vin-format"
|
disableAutoFill
|
||||||
:isDisabled="isVinFieldReadOnly"
|
validationRules="vin-required|vin-format"
|
||||||
/>
|
:isDisabled="isVinFieldReadOnly"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row my-2">
|
||||||
<div class="row my-2">
|
<div class="col">
|
||||||
<div class="col">
|
<vinInformation />
|
||||||
<vinInformation />
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row my-2">
|
||||||
<div class="row my-2">
|
<div class="col">
|
||||||
<div class="col">
|
<textboxQuestion
|
||||||
<textboxQuestion
|
cmsWidgetName="ServiceZIP"
|
||||||
cmsWidgetName="ServiceZIP"
|
v-model="zip"
|
||||||
v-model="zip"
|
inputId="zip"
|
||||||
inputId="zip"
|
mask="#####"
|
||||||
mask="#####"
|
isRequired
|
||||||
isRequired
|
disableAutoFill
|
||||||
disableAutoFill
|
validationRules="zip-required"
|
||||||
validationRules="zip-required"
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="row my-2">
|
||||||
<div class="row my-2">
|
<div class="col">
|
||||||
<div class="col">
|
<textboxQuestion
|
||||||
<textboxQuestion
|
cmsWidgetName="EmailAddress"
|
||||||
cmsWidgetName="EmailAddress"
|
v-model="email"
|
||||||
v-model="email"
|
inputId="email"
|
||||||
inputId="email"
|
isRequired
|
||||||
isRequired
|
disableAutoFill
|
||||||
disableAutoFill
|
validationRules="email-address-required|email-address-format"
|
||||||
validationRules="email-address-required|email-address-format"
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<alert
|
||||||
|
class="my-3"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="noMatchAlert"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
cmsWidgetName="NoMatchAlertWidget"
|
||||||
|
/>
|
||||||
|
<alert
|
||||||
|
class="my-3"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="vinNotFound"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
cmsWidgetName="VinNotFound"
|
||||||
|
/>
|
||||||
|
<alert
|
||||||
|
class="my-3"
|
||||||
|
:manualHeadline="PerfectMatchNewVinAlertReadOnlyHeader"
|
||||||
|
:manualCopy="PerfectMatchNewVinAlertReadOnlyBody"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="isVinFieldReadOnly"
|
||||||
|
alertClass="alert-success"
|
||||||
|
/>
|
||||||
|
<alert
|
||||||
|
class="my-3"
|
||||||
|
:manualHeadline="MatchedDifferentVehicleAlertHeader"
|
||||||
|
:manualCopy="MatchedDifferentVehicleAlertBody"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="isCarIdDifferent"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
/>
|
||||||
|
<alert
|
||||||
|
class="my-3"
|
||||||
|
:manualHeadline="NoServiceZipHeader"
|
||||||
|
:manualCopy="NoServiceZipBody"
|
||||||
|
v-model="customAlertData"
|
||||||
|
v-if="noServiceZip"
|
||||||
|
alertClass="alert-danger"
|
||||||
|
/>
|
||||||
|
<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-success"
|
||||||
|
cmsWidgetName="PerfectMatchNewVinAlert"
|
||||||
|
/>
|
||||||
|
<funnelFooter
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="funnelFooter"
|
||||||
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction"
|
||||||
|
/>
|
||||||
</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"
|
|
||||||
/>
|
|
||||||
<funnelFooter
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
ref="funnelFooter"
|
|
||||||
:isForwardActionDisabled="!meta.valid"
|
|
||||||
@back-clicked="backButtonAction"
|
|
||||||
@ForwardClicked="forwardButtonAction"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -121,6 +130,7 @@ import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-he
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
||||||
import vinInformation from "@/layouts/vin-lookup/vin-information/vin-information";
|
import vinInformation from "@/layouts/vin-lookup/vin-information/vin-information";
|
||||||
|
import loadingModal from '@/common-components/loading-modal/loading-modal.vue';
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
|
@ -130,13 +140,13 @@ import baseMixin from "@/mixins/base-mixin.js";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import { storeMutations } from "@/constants/store-mutations";
|
import { storeMutations } from "@/constants/store-mutations";
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
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 { required, regex } from "@/helpers/validation-rules";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, defineRule } from "vee-validate";
|
||||||
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
import { navigateAfterSaveToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
// DEFINE VALIDATION RULES
|
||||||
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
|
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||||
defineRule(
|
defineRule(
|
||||||
"email-address-required",
|
"email-address-required",
|
||||||
required(errorMessages.EMAIL_ADDRESS_REQUIRED)
|
required(errorMessages.EMAIL_ADDRESS_REQUIRED)
|
||||||
|
|
@ -175,44 +185,39 @@ export default {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
props: {
|
|
||||||
validationRules: String,
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
matchedDifferentVehicle: false,
|
isCarIdDifferent: false,
|
||||||
noMatchAlert: false,
|
|
||||||
noServiceZip: false,
|
noServiceZip: false,
|
||||||
vinFound: false,
|
|
||||||
vinFoundReadOnly: false,
|
|
||||||
foundWindshieldAlert: false,
|
|
||||||
vinNotFound: false,
|
vinNotFound: false,
|
||||||
perfectMatchNewVinAlert: false,
|
|
||||||
vin: this.getVinFromStore(),
|
vin: this.getVinFromStore(),
|
||||||
zip: this.getZipFromStore(),
|
zip: this.getZipFromStore(),
|
||||||
email: this.getEmailFromStore(),
|
email: this.getEmailFromStore(),
|
||||||
customAlertData: {},
|
customAlertData: {},
|
||||||
isCarIdDifferent: false,
|
|
||||||
previouslyEnteredCarId: '',
|
previouslyEnteredCarId: '',
|
||||||
invalidZip: '',
|
invalidZip: '',
|
||||||
|
vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
perfectMatchNewVinAlert() {
|
||||||
|
return this.vinPopulatedOnPageLoad && this.vin === this.getVinFromStore();
|
||||||
|
},
|
||||||
MatchedDifferentVehicleAlertHeader(){
|
MatchedDifferentVehicleAlertHeader(){
|
||||||
let text = this.getCmsContent("MatchedDifferentVehicle",
|
const text = this.getCmsContent("MatchedDifferentVehicle",
|
||||||
"HeadlineText").replaceAll("{custom:damage}", getDamageString());
|
"HeadlineText").replaceAll("{custom:damage}", getDamageString());
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
MatchedDifferentVehicleAlertBody(){
|
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}",
|
"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);
|
this.customAlertData?.vehicleInfo?.model);
|
||||||
|
|
||||||
return text;
|
return text;
|
||||||
},
|
},
|
||||||
NoServiceZipHeader(){
|
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;
|
return text;
|
||||||
},
|
},
|
||||||
|
|
@ -226,6 +231,13 @@ export default {
|
||||||
return this.getCmsContent("PerfectMatchNewVinAlert", "BodyText").replaceAll("{custom:damage}",
|
return this.getCmsContent("PerfectMatchNewVinAlert", "BodyText").replaceAll("{custom:damage}",
|
||||||
getDamageString())
|
getDamageString())
|
||||||
},
|
},
|
||||||
|
PerfectMatchNewVinAlertReadOnlyHeader () {
|
||||||
|
return this.getCmsContent("PerfectMatchNewVinAlertReadOnly", "HeadlineText");
|
||||||
|
},
|
||||||
|
PerfectMatchNewVinAlertReadOnlyBody () {
|
||||||
|
return this.getCmsContent("PerfectMatchNewVinAlertReadOnly", "BodyText").replaceAll("{custom:damage}",
|
||||||
|
getIsWindshieldOnly())
|
||||||
|
},
|
||||||
isVinFieldReadOnly(){
|
isVinFieldReadOnly(){
|
||||||
return this.$store.getters.payment.insuranceCoverage.isVerified;
|
return this.$store.getters.payment.insuranceCoverage.isVerified;
|
||||||
},
|
},
|
||||||
|
|
@ -242,13 +254,13 @@ export default {
|
||||||
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||||
},
|
},
|
||||||
getEmailFromStore(){
|
getEmailFromStore(){
|
||||||
return store.getters.order.customer.emailAddress
|
return store.getters.order.customer.emailAddress;
|
||||||
},
|
},
|
||||||
getVinFromStore(){
|
getVinFromStore(){
|
||||||
return store.getters.vehicle.vin
|
return store.getters.vehicle.vin;
|
||||||
},
|
},
|
||||||
getZipFromStore(){
|
getZipFromStore(){
|
||||||
return store.getters.vehicle.registration.zipCode
|
return store.getters.order.serviceLocation.zipCode;
|
||||||
},
|
},
|
||||||
attachCustomEvents() {
|
attachCustomEvents() {
|
||||||
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
this.prependActionToMethod(this, this.forwardButtonAction, () => {
|
||||||
|
|
@ -264,34 +276,36 @@ export default {
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
async forwardButtonAction() {
|
async forwardButtonAction() {
|
||||||
const zipValidation = await this.validateZip(this.zip);
|
const zipValidation = this.validateZip(this.zip);
|
||||||
if (!zipValidation.data.isServiceable) {
|
const vehicleLookup = this.lookupVehicle(this.vin);
|
||||||
|
const zipValidationResponse = await zipValidation;
|
||||||
|
const vehicleLookupResponse = await vehicleLookup.catch(() => {
|
||||||
|
this.vinNotFound = true;
|
||||||
|
this.$refs.funnelFooter.removeLoader();
|
||||||
|
this.noServiceZip = false;
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
if (!zipValidationResponse.data.isServiceable) {
|
||||||
this.customAlertData.zip = this.zip;
|
this.customAlertData.zip = this.zip;
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
this.noServiceZip = true;
|
this.noServiceZip = true;
|
||||||
this.invalidZip = this.zip;
|
this.invalidZip = this.zip;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const vehicleLookup = await this.lookupVehicle(this.vin).catch(() => {
|
this.isCarIdDifferent = vehicleLookupResponse.data.carId !== store.getters.vehicle.carId;
|
||||||
this.vinNotFound = true;
|
|
||||||
this.$refs.funnelFooter.removeLoader();
|
|
||||||
this.noServiceZip = false;
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
this.isCarIdDifferent = vehicleLookup.data.carId !== store.getters.vehicle.carId;
|
|
||||||
|
|
||||||
if (this.isCarIdDifferent && (vehicleLookup.data.carId !== this.previouslyEnteredCarId)) {
|
if (this.isCarIdDifferent && (vehicleLookupResponse.data.carId !== this.previouslyEnteredCarId)) {
|
||||||
this.previouslyEnteredCarId = vehicleLookup.data.carId;
|
this.previouslyEnteredCarId = vehicleLookupResponse.data.carId;
|
||||||
this.noServiceZip = false;
|
this.noServiceZip = false;
|
||||||
this.customAlertData.vehicleInfo = vehicleLookup.data;
|
this.customAlertData.vehicleInfo = vehicleLookupResponse.data;
|
||||||
this.$refs.funnelFooter.updateButtonText(`Continue with ${vehicleLookup.data.year} ${vehicleLookup.data.make} ${vehicleLookup.data.model}`);
|
this.$refs.funnelFooter.updateButtonText(`Continue with ${vehicleLookupResponse.data.year} ${vehicleLookupResponse.data.make} ${vehicleLookupResponse.data.model}`);
|
||||||
this.isVinValid = true;
|
this.isVinValid = true;
|
||||||
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vehicleLookup.data.carId);
|
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(vehicleLookupResponse.data.carId);
|
||||||
this.$refs.funnelFooter.removeLoader();
|
this.$refs.funnelFooter.removeLoader();
|
||||||
this.matchedDifferentVehicle = true;
|
this.isCarIdDifferent = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.updateStore(vehicleLookup.data);
|
this.updateStore(vehicleLookupResponse.data);
|
||||||
this.navigateForward();
|
this.navigateForward();
|
||||||
},
|
},
|
||||||
navigateForward(){
|
navigateForward(){
|
||||||
|
|
@ -299,6 +313,7 @@ export default {
|
||||||
this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD, this.$route, {}, { displayVehicleChangeAlert: true }, {});
|
this.$router.navigateAfterSave(this.navigationScenarios.CLICKED_FORWARD, this.$route, {}, { displayVehicleChangeAlert: true }, {});
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
|
this.$refs.loadingModal.showModal();
|
||||||
navigateAfterSaveToHeritageFunnel(this.$route);
|
navigateAfterSaveToHeritageFunnel(this.$route);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -341,6 +356,7 @@ export default {
|
||||||
alert,
|
alert,
|
||||||
funnelFooter,
|
funnelFooter,
|
||||||
vinInformation,
|
vinInformation,
|
||||||
|
loadingModal,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ const navigationScenarios = {
|
||||||
CONTINUING_WITH_MULTIPLE_PARTS: "CONTINUING_WITH_MULTIPLE_PARTS",
|
CONTINUING_WITH_MULTIPLE_PARTS: "CONTINUING_WITH_MULTIPLE_PARTS",
|
||||||
CONTINUING_WITH_SINGLE_PART: "CONTINUING_WITH_SINGLE_PART",
|
CONTINUING_WITH_SINGLE_PART: "CONTINUING_WITH_SINGLE_PART",
|
||||||
CONTINUING_WITH_MULTIPLE_VEHICLES: "CONTINUING_WITH_MULTIPLE_VEHICLES",
|
CONTINUING_WITH_MULTIPLE_VEHICLES: "CONTINUING_WITH_MULTIPLE_VEHICLES",
|
||||||
|
CONTINUING_WITH_DIFFERENT_GLASS: "CONTINUING_WITH_DIFFERENT_GLASS",
|
||||||
CLICKED_FORWARD_WITHOUT_VIN: "CLICKED_FORWARD_WITHOUT_VIN",
|
CLICKED_FORWARD_WITHOUT_VIN: "CLICKED_FORWARD_WITHOUT_VIN",
|
||||||
SELECTED_MANUAL_VIN: "SELECTED_MANUAL_VIN",
|
SELECTED_MANUAL_VIN: "SELECTED_MANUAL_VIN",
|
||||||
SELECTED_LICENSE_PLATE: "SELECTED_LICENSE_PLATE",
|
SELECTED_LICENSE_PLATE: "SELECTED_LICENSE_PLATE",
|
||||||
|
|
|
||||||
|
|
@ -102,19 +102,11 @@ const routingTable = [
|
||||||
maps: [
|
maps: [
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_BACK,
|
scenario: navigationScenarios.CLICKED_BACK,
|
||||||
destinationFmgPageValue: fmgPageValues.REVEAL,
|
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
||||||
},
|
|
||||||
{
|
|
||||||
scenario: navigationScenarios.CLICKED_BACK_WITH_VIN,
|
|
||||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
scenario: navigationScenarios.VIN_LOOKUP,
|
|
||||||
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
@ -125,18 +117,6 @@ const routingTable = [
|
||||||
scenario: navigationScenarios.CLICKED_BACK,
|
scenario: navigationScenarios.CLICKED_BACK,
|
||||||
destinationFmgPageValue: fmgPageValues.ESTIMATE,
|
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,
|
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||||
|
|
@ -155,9 +135,9 @@ const routingTable = [
|
||||||
destinationFmgPageValue: fmgPageValues.ADDRESS_VEHICLES,
|
destinationFmgPageValue: fmgPageValues.ADDRESS_VEHICLES,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
scenario: navigationScenarios.CONTINUING_WITH_DIFFERENT_GLASS,
|
||||||
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{fmgPageValue: fmgPageValues.ESTIMATE,
|
{fmgPageValue: fmgPageValues.ESTIMATE,
|
||||||
|
|
|
||||||
|
|
@ -135,26 +135,26 @@ export const mutations = {
|
||||||
updateRegistrationLicensePlate(state, licensePlate){
|
updateRegistrationLicensePlate(state, licensePlate){
|
||||||
state.order.vehicle.registration.licensePlate = licensePlate;
|
state.order.vehicle.registration.licensePlate = licensePlate;
|
||||||
},
|
},
|
||||||
|
updateRegistrationAddress(state, registrationAddress){
|
||||||
|
state.order.vehicle.registration.address = registrationAddress;
|
||||||
|
},
|
||||||
|
updateRegistrationCity(state, registrationCity){
|
||||||
|
state.order.vehicle.registration.city = registrationCity;
|
||||||
|
},
|
||||||
updateRegistrationState(state, registrationState){
|
updateRegistrationState(state, registrationState){
|
||||||
state.order.vehicle.registration.state = registrationState;
|
state.order.vehicle.registration.state = registrationState;
|
||||||
},
|
},
|
||||||
updateRegistrationZipCode(state, registrationZipCode){
|
updateRegistrationZipCode(state, registrationZipCode){
|
||||||
state.order.vehicle.registration.zipCode = registrationZipCode;
|
state.order.vehicle.registration.zipCode = registrationZipCode;
|
||||||
},
|
},
|
||||||
updateRegistrationAddress(state, registrationAddress){
|
updateServiceLocationZipCode(state, serviceLocationZip){
|
||||||
state.order.vehicle.registration.address = registrationAddress;
|
state.order.serviceLocation.zipCode = serviceLocationZip;
|
||||||
},
|
},
|
||||||
updateServiceLocationZipCode(state, serviceLocationZipCode){
|
|
||||||
state.order.serviceLocation.zipCode = serviceLocationZipCode;
|
|
||||||
},
|
|
||||||
updateRegistrationCity(state, serviceCity){
|
|
||||||
state.order.serviceLocation.city = serviceCity;
|
|
||||||
},
|
|
||||||
updateRegistrationFirstName(state, firstName){
|
updateRegistrationFirstName(state, firstName){
|
||||||
state.order.serviceLocation.firstName = firstName;
|
state.order.vehicle.registration.firstName = firstName;
|
||||||
},
|
},
|
||||||
updateRegistrationLastName(state, lastName){
|
updateRegistrationLastName(state, lastName){
|
||||||
state.order.serviceLocation.lastName = lastName;
|
state.order.vehicle.registration.lastName = lastName;
|
||||||
},
|
},
|
||||||
updateCustomerEmailAddress(state, customerEmailAddress){
|
updateCustomerEmailAddress(state, customerEmailAddress){
|
||||||
state.order.customer.emailAddress = customerEmailAddress;
|
state.order.customer.emailAddress = customerEmailAddress;
|
||||||
|
|
|
||||||
|
|
@ -9,4 +9,22 @@
|
||||||
.fade-enter-from,
|
.fade-enter-from,
|
||||||
.fade-leave-to {
|
.fade-leave-to {
|
||||||
opacity: 0;
|
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;
|
||||||
}
|
}
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
html {
|
html {
|
||||||
.has-error {
|
.has-error {
|
||||||
&.list-button,
|
&.list-button,
|
||||||
&.list-card {
|
&.list-card,
|
||||||
|
&.list-card.list-button {
|
||||||
border: 1px solid $red;
|
border: 1px solid $red;
|
||||||
color: $red;
|
color: $red;
|
||||||
input[type=checkbox]:focus + label,
|
input[type=checkbox]:focus + label,
|
||||||
|
|
@ -15,6 +16,14 @@ html {
|
||||||
box-shadow: 0px 0px 0px 4px $red-200;
|
box-shadow: 0px 0px 0px 4px $red-200;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
}
|
}
|
||||||
|
label {
|
||||||
|
border: 1px solid transparent;
|
||||||
|
}
|
||||||
|
label:hover {
|
||||||
|
box-shadow: 0px 0px 0px 4px $red-200;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid $red;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
&.list-button-horizontal {
|
&.list-button-horizontal {
|
||||||
color: $red;
|
color: $red;
|
||||||
|
|
@ -106,14 +115,17 @@ html {
|
||||||
color: $red;
|
color: $red;
|
||||||
font-size: .875rem;
|
font-size: .875rem;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
|
height: 1.5rem;
|
||||||
|
margin-top: .25rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.form-test-invalid {
|
.form-test-invalid {
|
||||||
&.btn.btn-primary {
|
&.btn.btn-primary {
|
||||||
color: $gray;
|
color: $gray-600;
|
||||||
background: $gray-200;
|
background: $gray-200;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
|
font-weight: $font-weight-normal;
|
||||||
}
|
}
|
||||||
&.btn.btn-primary:hover,
|
&.btn.btn-primary:hover,
|
||||||
&.btn.btn-primary:focus,
|
&.btn.btn-primary:focus,
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,15 @@ body {
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.sub-container{
|
||||||
|
&.make-tall {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.sr-only {
|
.sr-only {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: -10000px;
|
left: -10000px;
|
||||||
|
|
@ -34,4 +43,8 @@ body {
|
||||||
height: 1px;
|
height: 1px;
|
||||||
overflow: hidden;
|
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')
|
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 = {
|
const mockMixin = {
|
||||||
|
|
|
||||||
|
|
@ -4,16 +4,16 @@
|
||||||
role="alert"
|
role="alert"
|
||||||
:class="[isDismissible ? 'alert-dismissible' : '', this.alertClass]"
|
:class="[isDismissible ? 'alert-dismissible' : '', this.alertClass]"
|
||||||
>
|
>
|
||||||
<p class="m-0 fw-bold small alert-heading">{{ alertHeadline }}</p>
|
<p class="m-0 fw-bold alert-heading">{{ alertHeadline }}</p>
|
||||||
<p v-if="splitAlertCopyForLink.length">
|
<p v-if="splitAlertCopyForLink.length">
|
||||||
<template v-for="copy in splitAlertCopyForLink" :key="copy">
|
<template v-for="copy in splitAlertCopyForLink" :key="copy">
|
||||||
<span v-if="copy.includes('routerLink:')" class="m-0 text-body small">
|
<span v-if="copy.includes('routerLink:')" class="m-0 text-body">
|
||||||
<router-link :to="{query: {fmgPage: `${copy.split(':')[1].split(',')[0]}`}, name: 'root'}">{{ copy.split(':')[1].split(',')[1] }}</router-link>
|
<router-link :to="{query: {fmgPage: `${copy.split(':')[1].split(',')[0]}`}, name: 'root'}">{{ copy.split(':')[1].split(',')[1] }}</router-link>
|
||||||
</span>
|
</span>
|
||||||
<span v-else class="m-0 text-body small" v-html="copy"></span>
|
<span v-else class="m-0 text-body" v-html="copy"></span>
|
||||||
</template>
|
</template>
|
||||||
</p>
|
</p>
|
||||||
<p v-else class="m-0 text-body small" v-html="alertCopy"></p>
|
<p v-else class="m-0 text-body" v-html="alertCopy"></p>
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="btn-close p-2"
|
class="btn-close p-2"
|
||||||
|
|
@ -129,8 +129,8 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
& p {
|
& p {
|
||||||
font-size: 14px;
|
font-size: .875rem;
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0.25rem !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="list-group list-button d-flex flex-column w-100 mb-2"
|
class="list-group list-button rounded-3 d-flex flex-column w-100 mb-2"
|
||||||
:class="[(errors.length > 0 || hasError) ? 'has-error' : '']"
|
:class="[(errors.length > 0 || hasError) ? 'has-error' : '']"
|
||||||
@keyup.space="triggerButton()"
|
@keyup.space="triggerButton()"
|
||||||
@keyup.up="handleKeyupArrow()"
|
@keyup.up="handleKeyupArrow()"
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ a {
|
||||||
&.navigation-link {
|
&.navigation-link {
|
||||||
color: $black;
|
color: $black;
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
text-transform: capitalize;
|
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
&.footer-link {
|
&.footer-link {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue