Baseline linting for the remainder of the layout pages and the router folder.
This commit is contained in:
parent
8dc547ec39
commit
f65832ab23
43 changed files with 1632 additions and 1728 deletions
|
|
@ -5,7 +5,7 @@ const errorMessages = {
|
|||
PASSENGER_SIDE_OPTIONS_REQUIRED: 'Please select window',
|
||||
WINDSHIELD_DAMAGE_TYPE_REQUIRED: 'Please select windshield damage',
|
||||
WINDSHIELD_CHIP_COUNT_REQUIRED: 'Please select chip(s)',
|
||||
WINSHIELD_REPLACE_OPTIONS_REQUIRED: 'Please select windshield part',
|
||||
WINDSHIELD_REPLACE_OPTIONS_REQUIRED: 'Please select windshield part',
|
||||
REPLACE_OPTIONS_REQUIRED: 'Please select rear window type',
|
||||
STREET_ADDRESS_REQUIRED: 'Please enter your street address',
|
||||
CITY_REQUIRED: 'Please enter your city',
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget"/>
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2 confirmation">
|
||||
<p>Placeholder for tpa-confrimation page</p>
|
||||
<p>Placeholder for tpa-confirmation page</p>
|
||||
<siteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction"
|
||||
/>
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -27,15 +30,15 @@ import { settleAllPromises } from '@/helpers/layout-helper';
|
|||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
export default {
|
||||
name: 'tpa-confirmation',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
data() {
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
|
@ -46,11 +49,17 @@ export default {
|
|||
promise: cmsContentPromise
|
||||
}];
|
||||
// use resultMap to populate layout content.
|
||||
let resultMap = await settleAllPromises(promiseResultMap);
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
},
|
||||
methods:
|
||||
{
|
||||
backButtonAction() {
|
||||
|
|
@ -61,20 +70,13 @@ export default {
|
|||
},
|
||||
|
||||
navigateForward() {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
Form
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.confirmation p{
|
||||
margin-bottom:0.75rem;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget"/>
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2 search">
|
||||
<p>Placeholder for TPA-Search</p>
|
||||
<siteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction"
|
||||
/>
|
||||
@back-clicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -29,9 +32,13 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
|||
|
||||
export default {
|
||||
name: 'tpa-search',
|
||||
mixins: [BaseFormMixin],
|
||||
data() {
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
|
@ -42,33 +49,30 @@ export default {
|
|||
promise: cmsContentPromise
|
||||
}];
|
||||
// use resultMap to populate layout content.
|
||||
let resultMap = await settleAllPromises(promiseResultMap);
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
data() {
|
||||
},
|
||||
methods:
|
||||
{
|
||||
backButtonAction() {
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||
},
|
||||
forwardButtonAction() {
|
||||
return this.navigateForward();
|
||||
},
|
||||
navigateForward() {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
Form,
|
||||
}
|
||||
}
|
||||
</script><style lang="scss">
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.search p{
|
||||
margin-bottom:0.75rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,17 +1,20 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget"/>
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2 submit">
|
||||
<p>Placeholder for TPA-Submit</p>
|
||||
<siteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction"
|
||||
/>
|
||||
@back-clicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -31,14 +34,12 @@ import { useMainStore } from '@/store';
|
|||
|
||||
export default {
|
||||
name: 'tpa-submit',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
data() {
|
||||
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
|
@ -51,11 +52,18 @@ export default {
|
|||
}];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
let resultMap = await settleAllPromises(promiseResultMap);
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
|
||||
},
|
||||
methods:
|
||||
{
|
||||
|
|
@ -68,20 +76,13 @@ export default {
|
|||
},
|
||||
|
||||
navigateForward() {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
Form
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.submit {
|
||||
|
||||
margin-bottom:0.75rem;
|
||||
|
|
|
|||
|
|
@ -33,11 +33,9 @@ describe('damage-location-question.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
damageLocationQuestion.methods.initializeComponent.call(
|
||||
wrapper.vm,
|
||||
damageLocationQuestion.methods.initializeComponent.call(wrapper.vm,
|
||||
damageOptions,
|
||||
'car-group'
|
||||
);
|
||||
'car-group');
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.damageOptions).toStrictEqual({
|
||||
|
|
@ -66,7 +64,7 @@ function setupMocks({
|
|||
};
|
||||
mountOptions.propsData = {
|
||||
modelValue: modelValueProp,
|
||||
isMultiSelect: isMultiSelect
|
||||
isMultiSelect
|
||||
};
|
||||
mountOptions.mixins = [mockMixin];
|
||||
|
||||
|
|
@ -74,7 +72,7 @@ function setupMocks({
|
|||
|
||||
// Mock CMS content
|
||||
const cmsContent = {
|
||||
groupName: groupName,
|
||||
groupName,
|
||||
QuestionText: cmsQuestionText,
|
||||
Answers: cmsAnswers
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
<template>
|
||||
<div class="damage-location-question">
|
||||
<buttonQuestion
|
||||
v-model="selectedValues"
|
||||
:questionText="questionText"
|
||||
isMultiSelect
|
||||
:answers="answersToDisplay"
|
||||
:groupName="groupName"
|
||||
buttonTypeString="listCard"
|
||||
isRequired
|
||||
v-model="selectedValues"
|
||||
validationRules="damage-location-required" />
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -22,21 +22,20 @@ import { errorMessages } from '@/constants/error-messages';
|
|||
defineRule('damage-location-required', required(errorMessages.DAMAGE_LOCATION_REQUIRED));
|
||||
|
||||
export default {
|
||||
name: 'damageLocationQuestion',
|
||||
data() {
|
||||
return {
|
||||
damageOptions: Object
|
||||
};
|
||||
name: 'damage-location-question',
|
||||
components: {
|
||||
buttonQuestion
|
||||
},
|
||||
props: {
|
||||
modelValue: Array,
|
||||
groupName: String,
|
||||
cmsWidgetName: String
|
||||
},
|
||||
methods: {
|
||||
initializeComponent(damageOptions) {
|
||||
this.damageOptions = damageOptions;
|
||||
}
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
damageOptions: Object
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
|
|
@ -46,10 +45,10 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
},
|
||||
selectedValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
},
|
||||
|
|
@ -57,8 +56,8 @@ export default {
|
|||
return {
|
||||
Windshield: true,
|
||||
SideDoor:
|
||||
this.damageOptions.driverSideOptions.availableReplacementOptions.length ||
|
||||
this.damageOptions.passengerSideOptions.availableReplacementOptions.length,
|
||||
this.damageOptions.driverSideOptions.availableReplacementOptions.length
|
||||
|| this.damageOptions.passengerSideOptions.availableReplacementOptions.length,
|
||||
RearWindow: this.damageOptions.backGlassOptions.availableReplacementOptions.length
|
||||
};
|
||||
},
|
||||
|
|
@ -67,8 +66,8 @@ export default {
|
|||
? this.answersFromCms.filter((ans) => {
|
||||
const name = ans.Name.split('-');
|
||||
return (
|
||||
name[0].toUpperCase() === this.mainStore.vehicle.category &&
|
||||
this.damageOptionsMap[name[1]]
|
||||
name[0].toUpperCase() === this.mainStore.vehicle.category
|
||||
&& this.damageOptionsMap[name[1]]
|
||||
);
|
||||
})
|
||||
: [];
|
||||
|
|
@ -79,8 +78,10 @@ export default {
|
|||
});
|
||||
}
|
||||
},
|
||||
components: {
|
||||
buttonQuestion
|
||||
methods: {
|
||||
initializeComponent(damageOptions) {
|
||||
this.damageOptions = damageOptions;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -26,11 +26,9 @@ describe('replace-options-question.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
replaceOptionsQuestion.methods.initializeComponent.call(
|
||||
wrapper.vm,
|
||||
replaceOptionsQuestion.methods.initializeComponent.call(wrapper.vm,
|
||||
replaceOptions,
|
||||
'car-group'
|
||||
);
|
||||
'car-group');
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.replaceOptions).toStrictEqual(['Windshield', 'FrontDoor']);
|
||||
|
|
@ -71,12 +69,10 @@ describe('replace-options-question.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
wrapper.vm.$options.methods.initializeComponent.call(
|
||||
wrapper.vm,
|
||||
wrapper.vm.$options.methods.initializeComponent.call(wrapper.vm,
|
||||
cmsContent,
|
||||
replaceOptions,
|
||||
'car-group'
|
||||
);
|
||||
'car-group');
|
||||
wrapper.vm.$options.watch.isAvailable.call(wrapper.vm, true);
|
||||
|
||||
// Assert
|
||||
|
|
@ -106,9 +102,9 @@ function setupMocks({
|
|||
};
|
||||
mountOptions.propsData = {
|
||||
modelValue: modelValueProp,
|
||||
isAvailable: isAvailable,
|
||||
isMultiSelect: isMultiSelect,
|
||||
filterByVehicleCategory: filterByVehicleCategory,
|
||||
isAvailable,
|
||||
isMultiSelect,
|
||||
filterByVehicleCategory
|
||||
};
|
||||
mountOptions.mixins = [mockMixin];
|
||||
|
||||
|
|
@ -121,7 +117,7 @@ function setupMocks({
|
|||
|
||||
// Mock CMS content
|
||||
const cmsContent = {
|
||||
groupName: groupName,
|
||||
groupName,
|
||||
QuestionText: cmsQuestionText,
|
||||
Answers: cmsAnswers
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,18 +1,20 @@
|
|||
<template>
|
||||
<transition name="fade" mode="out-in">
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
v-if="shouldDisplayReplaceOptionsQuestion"
|
||||
class="replace-options-question"
|
||||
:class="this.answersToDisplay.length < 2 ? 'd-none' : ''"
|
||||
:class="answersToDisplay.length < 2 ? 'd-none' : ''"
|
||||
aria-live="polite">
|
||||
<buttonQuestion
|
||||
v-model="selectedValues"
|
||||
isWide
|
||||
:questionText="questionText"
|
||||
:isMultiSelect="isMultiSelect"
|
||||
:answers="answersToDisplay"
|
||||
:groupName="groupName"
|
||||
buttonTypeString="listCard"
|
||||
v-model="selectedValues"
|
||||
:validationRules="validationRules"
|
||||
:suppressError="suppressError"
|
||||
:isRequired="isRequired" />
|
||||
|
|
@ -24,11 +26,9 @@
|
|||
import buttonQuestion from '@/digital-components/button-question/button-question';
|
||||
|
||||
export default {
|
||||
name: 'replaceOptionsQuestion',
|
||||
data() {
|
||||
return {
|
||||
replaceOptions: this.isMultiSelect ? [] : ''
|
||||
};
|
||||
name: 'replace-options-question',
|
||||
components: {
|
||||
buttonQuestion
|
||||
},
|
||||
props: {
|
||||
isAvailable: Boolean,
|
||||
|
|
@ -41,18 +41,11 @@ export default {
|
|||
cmsWidgetName: String,
|
||||
isRequired: Boolean
|
||||
},
|
||||
methods: {
|
||||
initializeComponent(replaceOptions) {
|
||||
this.replaceOptions = replaceOptions;
|
||||
},
|
||||
updateSelectedValues() {
|
||||
// UPDATE SELECTEDVALUES IF ONLY ONE ANSWER
|
||||
if (Array.isArray(this.answersToDisplay) && this.answersToDisplay.length === 1) {
|
||||
this.selectedValues = this.isMultiSelect
|
||||
? [this.answersToDisplay[0].Name]
|
||||
: this.answersToDisplay[0].Name;
|
||||
}
|
||||
}
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
replaceOptions: this.isMultiSelect ? [] : ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
|
|
@ -62,10 +55,10 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
},
|
||||
selectedValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
},
|
||||
|
|
@ -74,8 +67,8 @@ export default {
|
|||
? this.answersFromCms.filter((ans) => {
|
||||
const name = ans.Name.split('-');
|
||||
return this.filterByVehicleCategory
|
||||
? name[0].toUpperCase() === this.mainStore.vehicle.category &&
|
||||
this.replaceOptions.includes(name[1])
|
||||
? name[0].toUpperCase() === this.mainStore.vehicle.category
|
||||
&& this.replaceOptions.includes(name[1])
|
||||
: this.replaceOptions.includes(ans.Name);
|
||||
})
|
||||
: [];
|
||||
|
|
@ -93,6 +86,7 @@ export default {
|
|||
watch: {
|
||||
isAvailable(val) {
|
||||
// CHECK TO UPDATE SELECTED VALUES WHEN ISAVAILABLE IS TRUE
|
||||
// eslint-disable-next-line no-unused-expressions
|
||||
val && this.updateSelectedValues();
|
||||
},
|
||||
shouldDisplayReplaceOptionsQuestion(shouldDisplayReplaceOptionsQuestion) {
|
||||
|
|
@ -101,8 +95,18 @@ export default {
|
|||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
buttonQuestion
|
||||
methods: {
|
||||
initializeComponent(replaceOptions) {
|
||||
this.replaceOptions = replaceOptions;
|
||||
},
|
||||
updateSelectedValues() {
|
||||
// UPDATE SELECTEDVALUES IF ONLY ONE ANSWER
|
||||
if (Array.isArray(this.answersToDisplay) && this.answersToDisplay.length === 1) {
|
||||
this.selectedValues = this.isMultiSelect
|
||||
? [this.answersToDisplay[0].Name]
|
||||
: this.answersToDisplay[0].Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -69,19 +69,17 @@ describe('replace-options-question.vue', () => {
|
|||
driverSideReplaceOptions,
|
||||
passengerSideReplaceOptions,
|
||||
driverSideOptions,
|
||||
passengerSideOptions,
|
||||
passengerSideOptions
|
||||
} = setupMocks({});
|
||||
|
||||
// Act
|
||||
sideDoorOptions.methods.initializeComponent.call(
|
||||
wrapper.vm,
|
||||
sideDoorOptions.methods.initializeComponent.call(wrapper.vm,
|
||||
cmsContent,
|
||||
driverSideReplaceOptions,
|
||||
passengerSideReplaceOptions,
|
||||
driverSideOptions,
|
||||
passengerSideOptions,
|
||||
'car-group'
|
||||
);
|
||||
'car-group');
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.answersToDisplay).toStrictEqual([]);
|
||||
|
|
@ -110,8 +108,8 @@ function setupMocks({
|
|||
};
|
||||
mountOptions.propsData = {
|
||||
modelValue: modelValueProp,
|
||||
groupName: groupName,
|
||||
selectedDamageLocations: selectedDamageLocations,
|
||||
groupName,
|
||||
selectedDamageLocations
|
||||
};
|
||||
mountOptions.mixins = [mockMixin];
|
||||
|
||||
|
|
@ -122,7 +120,7 @@ function setupMocks({
|
|||
OptionsWrapper[1].vm.initializeComponent = replaceOptionsQuestion.methods.initializeComponent;
|
||||
// Mock CMS content
|
||||
const cmsContent = {
|
||||
groupName: groupName,
|
||||
groupName,
|
||||
QuestionText: cmsQuestionText,
|
||||
Answers: cmsAnswers
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,39 +1,41 @@
|
|||
<template>
|
||||
<div class="side-door-options">
|
||||
<transition name="fade" mode="out-in">
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
class="side-doors"
|
||||
v-if="selectedDamageLocations.includes('SideDoor')"
|
||||
class="side-doors"
|
||||
aria-live="polite">
|
||||
<buttonQuestion
|
||||
v-model="selectedDoorSidesValues"
|
||||
:questionText="questionText"
|
||||
isMultiSelect
|
||||
:answers="answersToDisplay"
|
||||
:groupName="groupName"
|
||||
buttonTypeString="listCard"
|
||||
v-model="selectedDoorSidesValues"
|
||||
validationRules="damage-side-required"
|
||||
isRequired />
|
||||
</div>
|
||||
</transition>
|
||||
<replaceOptionsQuestion
|
||||
ref="driverSideOptions"
|
||||
v-model="selectedDriverSideReplaceOptionsValues"
|
||||
cmsWidgetName="DriverSideReplaceOptionsQuestion"
|
||||
:isAvailable="isDriverSideReplaceOptionsQuestionAvailable"
|
||||
groupName="driverSideOptions"
|
||||
isMultiSelect
|
||||
filterByVehicleCategory
|
||||
v-model="selectedDriverSideReplaceOptionsValues"
|
||||
validationRules="driver-side-options-required"
|
||||
isRequired />
|
||||
<replaceOptionsQuestion
|
||||
ref="passengerSideOptions"
|
||||
v-model="selectedPassengerSideReplaceOptionsValues"
|
||||
cmsWidgetName="PassengerSideReplaceOptionsQuestion"
|
||||
:isAvailable="isPassengerSideReplaceOptionsQuestionAvailable"
|
||||
groupName="passengerSideOptions"
|
||||
isMultiSelect
|
||||
filterByVehicleCategory
|
||||
v-model="selectedPassengerSideReplaceOptionsValues"
|
||||
validationRules="passenger-side-options-required"
|
||||
isRequired />
|
||||
</div>
|
||||
|
|
@ -53,30 +55,18 @@ defineRule('driver-side-options-required', required(errorMessages.DRIVER_SIDE_OP
|
|||
defineRule('passenger-side-options-required', required(errorMessages.PASSENGER_SIDE_OPTIONS_REQUIRED));
|
||||
|
||||
export default {
|
||||
name: 'sideDoorOptions',
|
||||
name: 'side-door-options',
|
||||
components: {
|
||||
buttonQuestion,
|
||||
replaceOptionsQuestion
|
||||
},
|
||||
props: {
|
||||
groupName: String,
|
||||
modelValue: Object,
|
||||
selectedDamageLocations: Array,
|
||||
cmsWidgetName: String
|
||||
},
|
||||
methods: {
|
||||
initializeComponent(driverSideOptions, passengerSideOptions) {
|
||||
this.$refs.driverSideOptions.initializeComponent(driverSideOptions);
|
||||
this.$refs.passengerSideOptions.initializeComponent(passengerSideOptions);
|
||||
},
|
||||
getSideDoorReplacementOptions(
|
||||
selectedDoorSides,
|
||||
selectedDriverSideReplaceOptions,
|
||||
selectedPassengerSideReplaceOptions
|
||||
) {
|
||||
return {
|
||||
selectedDoorSides: selectedDoorSides,
|
||||
selectedDriverSideReplaceOptions: selectedDriverSideReplaceOptions,
|
||||
selectedPassengerSideReplaceOptions: selectedPassengerSideReplaceOptions
|
||||
};
|
||||
},
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||
|
|
@ -85,47 +75,41 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
},
|
||||
selectedValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
},
|
||||
selectedDoorSidesValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.selectedValues.selectedDoorSides;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.selectedValues = this.getSideDoorReplacementOptions(
|
||||
newValue,
|
||||
set(newValue) {
|
||||
this.selectedValues = this.getSideDoorReplacementOptions(newValue,
|
||||
this.selectedValues.selectedDriverSideReplaceOptions,
|
||||
this.selectedValues.selectedPassengerSideReplaceOptions
|
||||
);
|
||||
this.selectedValues.selectedPassengerSideReplaceOptions);
|
||||
}
|
||||
},
|
||||
selectedDriverSideReplaceOptionsValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.selectedValues.selectedDriverSideReplaceOptions;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.selectedValues = this.getSideDoorReplacementOptions(
|
||||
this.selectedValues.selectedDoorSides,
|
||||
set(newValue) {
|
||||
this.selectedValues = this.getSideDoorReplacementOptions(this.selectedValues.selectedDoorSides,
|
||||
newValue,
|
||||
this.selectedValues.selectedPassengerSideReplaceOptions
|
||||
);
|
||||
this.selectedValues.selectedPassengerSideReplaceOptions);
|
||||
}
|
||||
},
|
||||
selectedPassengerSideReplaceOptionsValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.selectedValues.selectedPassengerSideReplaceOptions;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.selectedValues = this.getSideDoorReplacementOptions(
|
||||
this.selectedValues.selectedDoorSides,
|
||||
set(newValue) {
|
||||
this.selectedValues = this.getSideDoorReplacementOptions(this.selectedValues.selectedDoorSides,
|
||||
this.selectedValues.selectedDriverSideReplaceOptions,
|
||||
newValue
|
||||
);
|
||||
newValue);
|
||||
}
|
||||
},
|
||||
answersToDisplay() {
|
||||
|
|
@ -144,24 +128,35 @@ export default {
|
|||
},
|
||||
isDriverSideReplaceOptionsQuestionAvailable() {
|
||||
return (
|
||||
Array.isArray(this.selectedDoorSidesValues) &&
|
||||
this.selectedDoorSidesValues.includes(damageLocationsSelected.DRIVERSIDE) &&
|
||||
Array.isArray(this.selectedDamageLocations) &&
|
||||
this.selectedDamageLocations.includes(damageLocationsSelected.SIDEDOOR)
|
||||
Array.isArray(this.selectedDoorSidesValues)
|
||||
&& this.selectedDoorSidesValues.includes(damageLocationsSelected.DRIVERSIDE)
|
||||
&& Array.isArray(this.selectedDamageLocations)
|
||||
&& this.selectedDamageLocations.includes(damageLocationsSelected.SIDEDOOR)
|
||||
);
|
||||
},
|
||||
isPassengerSideReplaceOptionsQuestionAvailable() {
|
||||
return (
|
||||
Array.isArray(this.selectedDoorSidesValues) &&
|
||||
this.selectedDoorSidesValues.includes(damageLocationsSelected.PASSENGERSIDE) &&
|
||||
Array.isArray(this.selectedDamageLocations) &&
|
||||
this.selectedDamageLocations.includes(damageLocationsSelected.SIDEDOOR)
|
||||
Array.isArray(this.selectedDoorSidesValues)
|
||||
&& this.selectedDoorSidesValues.includes(damageLocationsSelected.PASSENGERSIDE)
|
||||
&& Array.isArray(this.selectedDamageLocations)
|
||||
&& this.selectedDamageLocations.includes(damageLocationsSelected.SIDEDOOR)
|
||||
);
|
||||
}
|
||||
},
|
||||
components: {
|
||||
buttonQuestion,
|
||||
replaceOptionsQuestion
|
||||
methods: {
|
||||
initializeComponent(driverSideOptions, passengerSideOptions) {
|
||||
this.$refs.driverSideOptions.initializeComponent(driverSideOptions);
|
||||
this.$refs.passengerSideOptions.initializeComponent(passengerSideOptions);
|
||||
},
|
||||
getSideDoorReplacementOptions(selectedDoorSides,
|
||||
selectedDriverSideReplaceOptions,
|
||||
selectedPassengerSideReplaceOptions) {
|
||||
return {
|
||||
selectedDoorSides,
|
||||
selectedDriverSideReplaceOptions,
|
||||
selectedPassengerSideReplaceOptions
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { createTestingPinia } from '@pinia/testing';
|
|||
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||
import { routerParams } from '@/router/router-params';
|
||||
import { vehicleCategories } from '@/constants/vehicle-categories';
|
||||
import VehicleDamageComponent from './vehicle-damage.vue';
|
||||
import VehicleDamageComponent from './vehicle-damage';
|
||||
|
||||
const mockRoute = {
|
||||
params: {}
|
||||
|
|
@ -74,9 +74,6 @@ describe('vehicle-damage.vue', () => {
|
|||
await flushPromises();
|
||||
expect(mockRouter.navigate).toHaveBeenCalledTimes(1);
|
||||
expect(mockRouter.navigate)
|
||||
.toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
|
||||
mockRoute
|
||||
);
|
||||
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_WITH_REPAIR, mockRoute);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,63 +1,67 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget"/>
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<div class="container-fluid pb-2">
|
||||
<div class="row mt-2 px-3">
|
||||
<div class="col">
|
||||
<alert
|
||||
ref="vehicleChangeAlert"
|
||||
v-if="shouldDisplayVehicleChangeAlert"
|
||||
class="mt-5 mb-0"
|
||||
cmsWidgetName="VehicleChangeAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
v-if="shouldDisplayVehicleChangeAlert"
|
||||
ref="vehicleChangeAlert"
|
||||
class="mt-5 mb-0"
|
||||
cmsWidgetName="VehicleChangeAlert"
|
||||
alertClass="alert-warning"
|
||||
:isDismissible="false" />
|
||||
<vehicleBanner
|
||||
class="mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
class="mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<damageLocationQuestion
|
||||
ref="damageLocation"
|
||||
cmsWidgetName="DamageLocationQuestion"
|
||||
v-model="selectedDamageLocations"
|
||||
groupName="DamageLocationQuestion" />
|
||||
ref="damageLocation"
|
||||
v-model="selectedDamageLocations"
|
||||
cmsWidgetName="DamageLocationQuestion"
|
||||
groupName="DamageLocationQuestion" />
|
||||
<windshieldOptions
|
||||
ref="windshieldOptions"
|
||||
v-model="selectedWindshieldOptions"
|
||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-3" />
|
||||
ref="windshieldOptions"
|
||||
v-model="selectedWindshieldOptions"
|
||||
:hasRepairReplaceConflict="hasRepairReplaceConflict"
|
||||
:hasSplitSingleConflict="hasSplitSingleConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-3" />
|
||||
<alert
|
||||
v-if="hasRepairReplaceConflict"
|
||||
class="my-5"
|
||||
cmsWidgetName="HasReplacementConflict"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
v-if="hasRepairReplaceConflict"
|
||||
class="my-5"
|
||||
cmsWidgetName="HasReplacementConflict"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<sideDoorOptions
|
||||
ref="sideDoorOptions"
|
||||
cmsWidgetName="SideDoorSideQuestion"
|
||||
groupName="SideDoorSideQuestion"
|
||||
v-model="sideDoorOptionsData"
|
||||
v-show="!hasRepairReplaceConflict"
|
||||
:selectedDamageLocations="selectedDamageLocations" class="mb-1"/>
|
||||
v-show="!hasRepairReplaceConflict"
|
||||
ref="sideDoorOptions"
|
||||
v-model="sideDoorOptionsData"
|
||||
cmsWidgetName="SideDoorSideQuestion"
|
||||
groupName="SideDoorSideQuestion"
|
||||
:selectedDamageLocations="selectedDamageLocations"
|
||||
class="mb-1" />
|
||||
<replaceOptionsQuestion
|
||||
ref="backGlassOptions"
|
||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
||||
v-model="selectedRearReplaceOptions"
|
||||
groupName="BackGlassReplaceOptionsQuestion"
|
||||
validationRules="replace-options-required" />
|
||||
ref="backGlassOptions"
|
||||
v-model="selectedRearReplaceOptions"
|
||||
cmsWidgetName="RearReplaceOptionsQuestion"
|
||||
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
|
||||
groupName="BackGlassReplaceOptionsQuestion"
|
||||
validationRules="replace-options-required" />
|
||||
<site-footer
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="backButtonAction"
|
||||
@forwardClicked="forwardButtonAction"
|
||||
ref="siteFooter"
|
||||
/>
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@backClicked="backButtonAction"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -94,6 +98,20 @@ defineRule('replace-options-required', required(errorMessages.REPLACE_OPTIONS_RE
|
|||
|
||||
export default {
|
||||
name: 'vehicle-damage',
|
||||
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
sideDoorOptions,
|
||||
damageLocationQuestion,
|
||||
windshieldOptions,
|
||||
replaceOptionsQuestion,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
alert
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const store = useMainStore();
|
||||
|
|
@ -120,16 +138,10 @@ export default {
|
|||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
vm.$refs.damageLocation.initializeComponent(resultMap.damageOptions);
|
||||
vm.$refs.sideDoorOptions.initializeComponent(
|
||||
resultMap.damageOptions.driverSideOptions.availableReplacementOptions,
|
||||
resultMap.damageOptions.passengerSideOptions.availableReplacementOptions
|
||||
);
|
||||
vm.$refs.windshieldOptions.initializeComponent(
|
||||
resultMap.damageOptions.windshieldOptions.availableReplacementOptions
|
||||
);
|
||||
vm.$refs.backGlassOptions.initializeComponent(
|
||||
resultMap.damageOptions.backGlassOptions.availableReplacementOptions
|
||||
);
|
||||
vm.$refs.sideDoorOptions.initializeComponent(resultMap.damageOptions.driverSideOptions.availableReplacementOptions,
|
||||
resultMap.damageOptions.passengerSideOptions.availableReplacementOptions);
|
||||
vm.$refs.windshieldOptions.initializeComponent(resultMap.damageOptions.windshieldOptions.availableReplacementOptions);
|
||||
vm.$refs.backGlassOptions.initializeComponent(resultMap.damageOptions.backGlassOptions.availableReplacementOptions);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
|
|
@ -149,6 +161,71 @@ export default {
|
|||
selectedRearReplaceOptions: this.getRearReplaceOptionsFromStore()
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isWindshieldDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD);
|
||||
},
|
||||
isSideDoorDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR);
|
||||
},
|
||||
isRearWindowDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW);
|
||||
},
|
||||
isWindshieldRepair() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation
|
||||
&& this.selectedWindshieldOptions.selectedWindshieldDamageType
|
||||
=== damageLocationsSelected.REPAIR
|
||||
);
|
||||
},
|
||||
isDriverSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
|
||||
return this
|
||||
.sideDoorOptionsData.selectedDoorSides
|
||||
.some((selectedDriverSide) => selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE);
|
||||
},
|
||||
isPassengerSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
|
||||
return this
|
||||
.sideDoorOptionsData.selectedDoorSides
|
||||
.some((selectedPassengerSide) => selectedPassengerSide.toUpperCase() === damageLocationsCms.PASSENGERSIDE);
|
||||
},
|
||||
hasRepairReplaceConflict() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation
|
||||
&& this.selectedDamageLocations.length > 1
|
||||
&& this.isWindshieldRepair
|
||||
);
|
||||
},
|
||||
hasSplitSingleConflict() {
|
||||
if (
|
||||
!this.selectedDamageLocations?.includes('Windshield')
|
||||
|| this.selectedWindshieldOptions.selectedWindshieldDamageType
|
||||
=== damageLocationsSelected.REPAIR
|
||||
|| !this.selectedWindshieldOptions.selectedWindshieldReplaceOptions
|
||||
) return false;
|
||||
|
||||
return (
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some((selectedSingleWindshield) => (
|
||||
selectedSingleWindshield.toUpperCase()
|
||||
=== damageLocationsSelected.SINGLE.toUpperCase()
|
||||
))
|
||||
&& (this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some((selectedDriverWindshield) => (
|
||||
selectedDriverWindshield.toUpperCase()
|
||||
=== damageLocationsSelected.DRIVER.toUpperCase()
|
||||
))
|
||||
|| this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some((selectedPassengerWindshield) => (
|
||||
selectedPassengerWindshield.toUpperCase()
|
||||
=== damageLocationsSelected.PASSENGER.toUpperCase()
|
||||
)))
|
||||
);
|
||||
},
|
||||
shouldDisplayVehicleChangeAlert() {
|
||||
return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
if (this.mainStore.order.vehicle.carId) {
|
||||
|
|
@ -163,31 +240,25 @@ export default {
|
|||
},
|
||||
|
||||
getDamageLocationsFromStore() {
|
||||
var glassSelections = [];
|
||||
const glassSelections = [];
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => {
|
||||
return glass.glassLocation === damageLocationsSelected.WINDSHIELD;
|
||||
}) ||
|
||||
this.mainStore.order.damage.isRepair
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.WINDSHIELD)
|
||||
|| this.mainStore.order.damage.isRepair
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.WINDSHIELD);
|
||||
}
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => {
|
||||
return (
|
||||
glass.glassLocation === damageLocationsSelected.DRIVER ||
|
||||
glass.glassLocation === damageLocationsSelected.PASSENGER
|
||||
);
|
||||
})
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => (
|
||||
glass.glassLocation === damageLocationsSelected.DRIVER
|
||||
|| glass.glassLocation === damageLocationsSelected.PASSENGER
|
||||
))
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.SIDEDOOR);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => {
|
||||
return glass.glassLocation === damageLocationsSelected.REAR;
|
||||
})
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.REAR)
|
||||
) {
|
||||
glassSelections.push(damageLocationsSelected.REARWINDOW);
|
||||
}
|
||||
|
|
@ -196,7 +267,7 @@ export default {
|
|||
},
|
||||
|
||||
getWindshieldOptionsFromStore() {
|
||||
var windShieldOptions = {
|
||||
const windShieldOptions = {
|
||||
selectedWindshieldDamageType: '',
|
||||
selectedWindshieldChipCount: null,
|
||||
selectedWindshieldReplaceOptions: []
|
||||
|
|
@ -209,48 +280,36 @@ export default {
|
|||
windShieldOptions.selectedWindshieldChipCount = this.mainStore.order.damage.numberOfChips;
|
||||
} else {
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => {
|
||||
return (
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName === damageLocationsSelected.SINGLE
|
||||
);
|
||||
})
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => (
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD
|
||||
&& glass.glassName === damageLocationsSelected.SINGLE
|
||||
))
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.SINGLE
|
||||
);
|
||||
windShieldOptions.selectedWindshieldDamageType
|
||||
= damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(damageLocationsSelected.SINGLE);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => {
|
||||
return (
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName === damageLocationsSelected.DRIVER
|
||||
);
|
||||
})
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => (
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD
|
||||
&& glass.glassName === damageLocationsSelected.DRIVER
|
||||
))
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.DRIVER
|
||||
);
|
||||
windShieldOptions.selectedWindshieldDamageType
|
||||
= damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(damageLocationsSelected.DRIVER);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => {
|
||||
return (
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD &&
|
||||
glass.glassName === damageLocationsSelected.PASSENGER
|
||||
);
|
||||
})
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => (
|
||||
glass.glassLocation === damageLocationsSelected.WINDSHIELD
|
||||
&& glass.glassName === damageLocationsSelected.PASSENGER
|
||||
))
|
||||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.PASSENGER
|
||||
);
|
||||
windShieldOptions.selectedWindshieldDamageType
|
||||
= damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(damageLocationsSelected.PASSENGER);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -258,19 +317,15 @@ export default {
|
|||
},
|
||||
|
||||
getDoorSidesFromStore() {
|
||||
var doorSides = [];
|
||||
const doorSides = [];
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => {
|
||||
return glass.glassLocation === damageLocationsSelected.DRIVER;
|
||||
})
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.DRIVER)
|
||||
) {
|
||||
doorSides.push(damageLocationsSelected.DRIVERSIDE);
|
||||
}
|
||||
|
||||
if (
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => {
|
||||
return glass.glassLocation === damageLocationsSelected.PASSENGER;
|
||||
})
|
||||
this.mainStore.order.damage.glassToReplace?.some((glass) => glass.glassLocation === damageLocationsSelected.PASSENGER)
|
||||
) {
|
||||
doorSides.push(damageLocationsSelected.PASSENGERSIDE);
|
||||
}
|
||||
|
|
@ -279,7 +334,7 @@ export default {
|
|||
},
|
||||
|
||||
getDriverSideReplaceOptionsFromStore() {
|
||||
var driverSideReplaceOptions = [];
|
||||
const driverSideReplaceOptions = [];
|
||||
|
||||
this.mainStore.order.damage.glassToReplace?.forEach((glass) => {
|
||||
if (glass.glassLocation === damageLocationsSelected.DRIVER) {
|
||||
|
|
@ -291,7 +346,7 @@ export default {
|
|||
},
|
||||
|
||||
getPassengerSideReplaceOptionsFromStore() {
|
||||
var passengerSideReplaceOptions = [];
|
||||
const passengerSideReplaceOptions = [];
|
||||
|
||||
this.mainStore.order.damage.glassToReplace?.forEach((glass) => {
|
||||
if (glass.glassLocation === damageLocationsSelected.PASSENGER) {
|
||||
|
|
@ -303,9 +358,8 @@ export default {
|
|||
},
|
||||
|
||||
getRearReplaceOptionsFromStore() {
|
||||
var rearReplaceOptions = this.mainStore.order.damage.glassToReplace?.filter(
|
||||
(glass) => glass.glassLocation === damageLocationsSelected.REAR
|
||||
)[0]?.glassName;
|
||||
const rearReplaceOptions = this.mainStore.order.damage
|
||||
.glassToReplace?.filter((glass) => glass.glassLocation === damageLocationsSelected.REAR)[0]?.glassName;
|
||||
|
||||
return rearReplaceOptions;
|
||||
},
|
||||
|
|
@ -319,37 +373,27 @@ export default {
|
|||
|
||||
navigateForward() {
|
||||
if (this.mainStore.damage.isRepair) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
|
||||
this.$route);
|
||||
} else if (this.mainStore.order.vehicle.vin) {
|
||||
// If vin already exists, navigate directly to vin-lookup
|
||||
if (this.mainStore.order.vehicle.vin) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_VIN,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_VIN,
|
||||
this.$route);
|
||||
} else {
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
|
||||
this.$route);
|
||||
}
|
||||
},
|
||||
|
||||
selectedGlassToReplace() {
|
||||
const selectedGlassToReplace = [];
|
||||
if (this.isWindshieldDamageLocation && !this.isWindshieldRepair) {
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach(
|
||||
(wsItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.WINDSHIELD,
|
||||
glassName: wsItem
|
||||
});
|
||||
}
|
||||
);
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach((wsItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.WINDSHIELD,
|
||||
glassName: wsItem
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isDriverSideReplace) {
|
||||
|
|
@ -362,14 +406,12 @@ export default {
|
|||
}
|
||||
|
||||
if (this.isPassengerSideReplace) {
|
||||
this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach(
|
||||
(passengerItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.PASSENGER,
|
||||
glassName: passengerItem
|
||||
});
|
||||
}
|
||||
);
|
||||
this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach((passengerItem) => {
|
||||
selectedGlassToReplace.push({
|
||||
glassLocation: damageLocationsSelected.PASSENGER,
|
||||
glassName: passengerItem
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
if (this.isRearWindowDamageLocation) {
|
||||
|
|
@ -381,103 +423,6 @@ export default {
|
|||
|
||||
return selectedGlassToReplace;
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isWindshieldDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => {
|
||||
return selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD;
|
||||
});
|
||||
},
|
||||
isSideDoorDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => {
|
||||
return selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR;
|
||||
});
|
||||
},
|
||||
isRearWindowDamageLocation() {
|
||||
return this.selectedDamageLocations.some((selectedDamages) => {
|
||||
return selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW;
|
||||
});
|
||||
},
|
||||
isWindshieldRepair() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation &&
|
||||
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
||||
damageLocationsSelected.REPAIR
|
||||
);
|
||||
},
|
||||
isDriverSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
|
||||
return this.sideDoorOptionsData.selectedDoorSides.some((selectedDriverSide) => {
|
||||
return selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE;
|
||||
});
|
||||
},
|
||||
isPassengerSideReplace() {
|
||||
if (!this.isSideDoorDamageLocation) return false;
|
||||
|
||||
return this.sideDoorOptionsData.selectedDoorSides.some((selectedPassengerSide) => {
|
||||
return selectedPassengerSide.toUpperCase() === damageLocationsCms.PASSENGERSIDE;
|
||||
});
|
||||
},
|
||||
hasRepairReplaceConflict() {
|
||||
return (
|
||||
this.isWindshieldDamageLocation &&
|
||||
this.selectedDamageLocations.length > 1 &&
|
||||
this.isWindshieldRepair
|
||||
);
|
||||
},
|
||||
hasSplitSingleConflict() {
|
||||
if (
|
||||
!this.selectedDamageLocations?.includes('Windshield') ||
|
||||
this.selectedWindshieldOptions.selectedWindshieldDamageType ===
|
||||
damageLocationsSelected.REPAIR ||
|
||||
!this.selectedWindshieldOptions.selectedWindshieldReplaceOptions
|
||||
)
|
||||
return false;
|
||||
|
||||
return (
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
||||
(selectedSingleWindshield) => {
|
||||
return (
|
||||
selectedSingleWindshield.toUpperCase() ===
|
||||
damageLocationsSelected.SINGLE.toUpperCase()
|
||||
);
|
||||
}
|
||||
) &&
|
||||
(this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
||||
(selectedDriverWindshield) => {
|
||||
return (
|
||||
selectedDriverWindshield.toUpperCase() ===
|
||||
damageLocationsSelected.DRIVER.toUpperCase()
|
||||
);
|
||||
}
|
||||
) ||
|
||||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
|
||||
(selectedPassengerWindshield) => {
|
||||
return (
|
||||
selectedPassengerWindshield.toUpperCase() ===
|
||||
damageLocationsSelected.PASSENGER.toUpperCase()
|
||||
);
|
||||
}
|
||||
))
|
||||
);
|
||||
},
|
||||
shouldDisplayVehicleChangeAlert() {
|
||||
return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT];
|
||||
}
|
||||
},
|
||||
|
||||
components: {
|
||||
siteHeader,
|
||||
siteFooter,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
sideDoorOptions,
|
||||
damageLocationQuestion,
|
||||
windshieldOptions,
|
||||
replaceOptionsQuestion,
|
||||
Form,
|
||||
alert
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ function setupMocks({
|
|||
// Mock props
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn(),
|
||||
getCmsContent: jest.fn()
|
||||
}
|
||||
};
|
||||
mountOptions.propsData = {
|
||||
|
|
@ -48,7 +48,7 @@ function setupMocks({
|
|||
|
||||
// Mock CMS content
|
||||
const cmsContent = {
|
||||
groupName: groupName,
|
||||
groupName,
|
||||
QuestionText: cmsQuestionText,
|
||||
Answers: cmsAnswers
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,13 +1,18 @@
|
|||
<template>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="windshield-chip-count-question" v-if="isAvailable" aria-live="polite">
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
v-if="isAvailable"
|
||||
class="windshield-chip-count-question"
|
||||
aria-live="polite">
|
||||
<buttonQuestion
|
||||
v-model="selectedValue"
|
||||
:questionText="questionText"
|
||||
:answers="answersFromCms"
|
||||
:groupName="groupName"
|
||||
buttonTypeString="listButtonHorizontal"
|
||||
useTextForValue
|
||||
v-model="selectedValue"
|
||||
:validationRules="validationRules"
|
||||
isRequired />
|
||||
</div>
|
||||
|
|
@ -18,7 +23,10 @@
|
|||
import buttonQuestion from '@/digital-components/button-question/button-question';
|
||||
|
||||
export default {
|
||||
name: 'windshieldOptions',
|
||||
name: 'windshield-options',
|
||||
components: {
|
||||
buttonQuestion
|
||||
},
|
||||
props: {
|
||||
modelValue: [String, Number],
|
||||
groupName: String,
|
||||
|
|
@ -26,6 +34,7 @@ export default {
|
|||
validationRules: String,
|
||||
cmsWidgetName: String
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||
|
|
@ -34,17 +43,14 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
},
|
||||
selectedValue: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
const numberValue = Number(newValue);
|
||||
this.$emit('update:modelValue', numberValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
buttonQuestion
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
<template>
|
||||
<transition name="fade" mode="out-in">
|
||||
<div class="windshield-damage-type-question" v-if="isAvailable" aria-live="polite">
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
v-if="isAvailable"
|
||||
class="windshield-damage-type-question"
|
||||
aria-live="polite">
|
||||
<buttonQuestion
|
||||
v-model="selectedValues"
|
||||
:questionText="questionText"
|
||||
:answers="answersFromCms"
|
||||
:groupName="groupName"
|
||||
buttonTypeString="listCard"
|
||||
v-model="selectedValues"
|
||||
:suppressError="suppressError"
|
||||
:validationRules="validationRules"
|
||||
isRequired />
|
||||
|
|
@ -18,7 +23,10 @@
|
|||
import buttonQuestion from '@/digital-components/button-question/button-question';
|
||||
|
||||
export default {
|
||||
name: 'windshieldDamageTypeQuestion',
|
||||
name: 'windshield-damage-type-question',
|
||||
components: {
|
||||
buttonQuestion
|
||||
},
|
||||
props: {
|
||||
modelValue: String,
|
||||
groupName: String,
|
||||
|
|
@ -27,6 +35,7 @@ export default {
|
|||
validationRules: String,
|
||||
cmsWidgetName: String
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||
|
|
@ -35,16 +44,13 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
},
|
||||
selectedValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
}
|
||||
},
|
||||
components: {
|
||||
buttonQuestion
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
<template>
|
||||
<div class="windshield-options">
|
||||
<windshieldDamageTypeQuestion
|
||||
v-model="selectedWindshieldDamageTypeValue"
|
||||
cmsWidgetName="WindshieldDamageTypeQuestion"
|
||||
:isAvailable="isWindshieldDamageLocation"
|
||||
:suppressError="hasRepairReplaceConflict || showNoReplacementAvailableError"
|
||||
groupName="WindshieldDamageTypeQuestion"
|
||||
v-model="selectedWindshieldDamageTypeValue"
|
||||
:validationRules="windshieldDamageTypeQuestionValidationRules" />
|
||||
<alert
|
||||
v-if="showNoReplacementAvailableError"
|
||||
|
|
@ -14,18 +14,18 @@
|
|||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<windshieldChipCountQuestion
|
||||
v-model="selectedWindshieldChipCountValues"
|
||||
cmsWidgetName="WindshieldChipCountQuestion"
|
||||
:isAvailable="isRepairOptionSelected && !hasRepairReplaceConflict"
|
||||
groupName="WindshieldChipCountQuestion"
|
||||
v-model="selectedWindshieldChipCountValues"
|
||||
validationRules="windshield-chip-count-required" />
|
||||
<replaceOptionsQuestion
|
||||
ref="replaceOptionsQuestion"
|
||||
v-model="selectedWindshieldReplaceOptionsValues"
|
||||
cmsWidgetName="WindshieldReplaceOptionsQuestion"
|
||||
:isAvailable="isReplaceOptionSelected"
|
||||
isMultiSelect
|
||||
groupName="WindshieldReplaceOptions"
|
||||
v-model="selectedWindshieldReplaceOptionsValues"
|
||||
validationRules="windshield-replace-options-required|prevent-split-and-single-together"
|
||||
:suppressError="hasSplitSingleConflict"
|
||||
isRequired />
|
||||
|
|
@ -39,8 +39,10 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import windshieldDamageTypeQuestion from '@/layouts/vehicle-damage/windshield-options/windshield-damage-type-question/windshield-damage-type-question';
|
||||
import windshieldChipCountQuestion from '@/layouts/vehicle-damage/windshield-options/windshield-chip-count-question/windshield-chip-count-question';
|
||||
import windshieldDamageTypeQuestion from
|
||||
'@/layouts/vehicle-damage/windshield-options/windshield-damage-type-question/windshield-damage-type-question';
|
||||
import windshieldChipCountQuestion from
|
||||
'@/layouts/vehicle-damage/windshield-options/windshield-chip-count-question/windshield-chip-count-question';
|
||||
import replaceOptionsQuestion from '@/layouts/vehicle-damage/replace-options-question/replace-options-question';
|
||||
import alert from '@/ux-components/alert/alert';
|
||||
|
||||
|
|
@ -50,38 +52,26 @@ import { errorMessages } from '@/constants/error-messages';
|
|||
import { damageLocationsSelected } from '@/constants/damage-locations-selected.js';
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule(
|
||||
'windshield-damage-type-required',
|
||||
required(errorMessages.WINDSHIELD_DAMAGE_TYPE_REQUIRED)
|
||||
);
|
||||
defineRule(
|
||||
'windshield-chip-count-required',
|
||||
required(errorMessages.WINDSHIELD_CHIP_COUNT_REQUIRED)
|
||||
);
|
||||
defineRule(
|
||||
'windshield-replace-options-required',
|
||||
required(errorMessages.WINSHIELD_REPLACE_OPTIONS_REQUIRED)
|
||||
);
|
||||
defineRule('windshield-damage-type-required',
|
||||
required(errorMessages.WINDSHIELD_DAMAGE_TYPE_REQUIRED));
|
||||
defineRule('windshield-chip-count-required',
|
||||
required(errorMessages.WINDSHIELD_CHIP_COUNT_REQUIRED));
|
||||
defineRule('windshield-replace-options-required',
|
||||
required(errorMessages.WINDSHIELD_REPLACE_OPTIONS_REQUIRED));
|
||||
|
||||
defineRule(
|
||||
'check-for-repair-and-replace',
|
||||
(selectedWindshieldDamageType, selectedDamageLocations) => {
|
||||
return (
|
||||
selectedWindshieldDamageType.toString() != damageLocationsSelected.REPAIR ||
|
||||
(!selectedDamageLocations.includes(damageLocationsSelected.WINDSHIELD) &&
|
||||
!selectedDamageLocations[0]?.includes(damageLocationsSelected.WINDSHIELD)) ||
|
||||
selectedDamageLocations[0].length === 1
|
||||
);
|
||||
}
|
||||
);
|
||||
defineRule('repair-only', (value) => {
|
||||
return value.toString() === damageLocationsSelected.REPAIR;
|
||||
});
|
||||
defineRule('check-for-repair-and-replace',
|
||||
(selectedWindshieldDamageType, selectedDamageLocations) => (
|
||||
selectedWindshieldDamageType.toString() !== damageLocationsSelected.REPAIR
|
||||
|| (!selectedDamageLocations.includes(damageLocationsSelected.WINDSHIELD)
|
||||
&& !selectedDamageLocations[0]?.includes(damageLocationsSelected.WINDSHIELD))
|
||||
|| selectedDamageLocations[0].length === 1
|
||||
));
|
||||
defineRule('repair-only', (value) => value.toString() === damageLocationsSelected.REPAIR);
|
||||
defineRule('prevent-split-and-single-together', (value) => {
|
||||
if (
|
||||
value.toString().toUpperCase().includes(damageLocationsSelected.SINGLE.toUpperCase()) &&
|
||||
(value.toString().toUpperCase().includes(damageLocationsSelected.DRIVER.toUpperCase()) ||
|
||||
value
|
||||
value.toString().toUpperCase().includes(damageLocationsSelected.SINGLE.toUpperCase())
|
||||
&& (value.toString().toUpperCase().includes(damageLocationsSelected.DRIVER.toUpperCase())
|
||||
|| value
|
||||
.toString()
|
||||
.toUpperCase()
|
||||
.includes(damageLocationsSelected.PASSENGER.toUpperCase()))
|
||||
|
|
@ -92,12 +82,12 @@ defineRule('prevent-split-and-single-together', (value) => {
|
|||
});
|
||||
|
||||
export default {
|
||||
name: 'windshieldOptions',
|
||||
|
||||
data() {
|
||||
return {
|
||||
windshieldAvailableReplacementOptions: Object
|
||||
};
|
||||
name: 'windshield-options',
|
||||
components: {
|
||||
windshieldDamageTypeQuestion,
|
||||
windshieldChipCountQuestion,
|
||||
replaceOptionsQuestion,
|
||||
alert
|
||||
},
|
||||
|
||||
props: {
|
||||
|
|
@ -106,102 +96,75 @@ export default {
|
|||
hasRepairReplaceConflict: Boolean,
|
||||
hasSplitSingleConflict: Boolean
|
||||
},
|
||||
|
||||
methods: {
|
||||
initializeComponent(windshieldAvailableReplacementOptions) {
|
||||
this.windshieldAvailableReplacementOptions = windshieldAvailableReplacementOptions;
|
||||
this.$refs.replaceOptionsQuestion.initializeComponent(
|
||||
windshieldAvailableReplacementOptions
|
||||
);
|
||||
},
|
||||
getWindshieldOptions(
|
||||
selectedWindshieldDamageType,
|
||||
selectedWindshieldChipCount,
|
||||
selectedWindshieldReplaceOptions
|
||||
) {
|
||||
// ONLY UPDATE THE NEW VALUE IF IT IS TRUTHY (NOT NULL)
|
||||
return {
|
||||
selectedWindshieldDamageType: selectedWindshieldDamageType
|
||||
? selectedWindshieldDamageType
|
||||
: this.selectedValues.selectedWindshieldDamageType,
|
||||
selectedWindshieldChipCount: selectedWindshieldChipCount
|
||||
? selectedWindshieldChipCount
|
||||
: this.selectedValues.selectedWindshieldChipCount,
|
||||
selectedWindshieldReplaceOptions: selectedWindshieldReplaceOptions
|
||||
? selectedWindshieldReplaceOptions
|
||||
: this.selectedValues.selectedWindshieldReplaceOptions,
|
||||
};
|
||||
}
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
windshieldAvailableReplacementOptions: Object
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
selectedValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
},
|
||||
selectedWindshieldDamageTypeValue: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.selectedDamageLocations.includes(damageLocationsSelected.WINDSHIELD)
|
||||
? this.selectedValues.selectedWindshieldDamageType
|
||||
: null;
|
||||
},
|
||||
set: function (newValue) {
|
||||
set(newValue) {
|
||||
this.selectedValues = this.getWindshieldOptions(newValue, null, null);
|
||||
},
|
||||
}
|
||||
},
|
||||
selectedWindshieldChipCountValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.selectedValues.selectedWindshieldChipCount;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.selectedValues = this.getWindshieldOptions(
|
||||
this.selectedWindshieldDamageTypeValue,
|
||||
set(newValue) {
|
||||
this.selectedValues = this.getWindshieldOptions(this.selectedWindshieldDamageTypeValue,
|
||||
newValue,
|
||||
null
|
||||
);
|
||||
null);
|
||||
}
|
||||
},
|
||||
selectedWindshieldReplaceOptionsValues: {
|
||||
get: function () {
|
||||
get() {
|
||||
return this.selectedValues.selectedWindshieldReplaceOptions;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.selectedValues = this.getWindshieldOptions(
|
||||
this.selectedWindshieldDamageTypeValue,
|
||||
set(newValue) {
|
||||
this.selectedValues = this.getWindshieldOptions(this.selectedWindshieldDamageTypeValue,
|
||||
null,
|
||||
newValue
|
||||
);
|
||||
newValue);
|
||||
}
|
||||
},
|
||||
isWindshieldDamageLocation() {
|
||||
return this.selectedDamageLocations.some(
|
||||
(selectedDamageLocation) =>
|
||||
selectedDamageLocation === damageLocationsSelected.WINDSHIELD
|
||||
);
|
||||
return this.selectedDamageLocations.some((selectedDamageLocation) =>
|
||||
selectedDamageLocation === damageLocationsSelected.WINDSHIELD);
|
||||
},
|
||||
isRepairOptionSelected() {
|
||||
if (!this.selectedWindshieldDamageTypeValue) return false;
|
||||
|
||||
return (
|
||||
this.selectedWindshieldDamageTypeValue === damageLocationsSelected.REPAIR &&
|
||||
this.isWindshieldDamageLocation
|
||||
this.selectedWindshieldDamageTypeValue === damageLocationsSelected.REPAIR
|
||||
&& this.isWindshieldDamageLocation
|
||||
);
|
||||
},
|
||||
isReplaceOptionSelected() {
|
||||
if (!this.selectedWindshieldDamageTypeValue) return false;
|
||||
|
||||
return (
|
||||
this.selectedWindshieldDamageTypeValue === damageLocationsSelected.REPLACE &&
|
||||
this.isWindshieldDamageLocation
|
||||
this.selectedWindshieldDamageTypeValue === damageLocationsSelected.REPLACE
|
||||
&& this.isWindshieldDamageLocation
|
||||
);
|
||||
},
|
||||
isWindshieldReplaceAvailable() {
|
||||
return !(
|
||||
Array.isArray(this.windshieldAvailableReplacementOptions) &&
|
||||
this.windshieldAvailableReplacementOptions.length < 1
|
||||
Array.isArray(this.windshieldAvailableReplacementOptions)
|
||||
&& this.windshieldAvailableReplacementOptions.length < 1
|
||||
);
|
||||
},
|
||||
isSplitWindshieldOption() {
|
||||
|
|
@ -219,8 +182,8 @@ export default {
|
|||
},
|
||||
windshieldDamageTypeQuestionValidationRules() {
|
||||
// Note: the validation rules string is not dynamic (it cannot be changed once component has been created)
|
||||
let validationRules =
|
||||
'windshield-damage-type-required|check-for-repair-and-replace:@DamageLocationQuestion';
|
||||
let validationRules
|
||||
= 'windshield-damage-type-required|check-for-repair-and-replace:@DamageLocationQuestion';
|
||||
// if vehicle has no windshield replacement option
|
||||
if (!this.isWindshieldReplaceAvailable) {
|
||||
validationRules = validationRules.concat('|repair-only');
|
||||
|
|
@ -228,11 +191,22 @@ export default {
|
|||
return validationRules;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
windshieldDamageTypeQuestion,
|
||||
windshieldChipCountQuestion,
|
||||
replaceOptionsQuestion,
|
||||
alert
|
||||
|
||||
methods: {
|
||||
initializeComponent(windshieldAvailableReplacementOptions) {
|
||||
this.windshieldAvailableReplacementOptions = windshieldAvailableReplacementOptions;
|
||||
this.$refs.replaceOptionsQuestion.initializeComponent(windshieldAvailableReplacementOptions);
|
||||
},
|
||||
getWindshieldOptions(selectedWindshieldDamageType,
|
||||
selectedWindshieldChipCount,
|
||||
selectedWindshieldReplaceOptions) {
|
||||
// ONLY UPDATE THE NEW VALUE IF IT IS TRUTHY (NOT NULL)
|
||||
return {
|
||||
selectedWindshieldDamageType: selectedWindshieldDamageType || this.selectedValues.selectedWindshieldDamageType,
|
||||
selectedWindshieldChipCount: selectedWindshieldChipCount || this.selectedValues.selectedWindshieldChipCount,
|
||||
selectedWindshieldReplaceOptions: selectedWindshieldReplaceOptions || this.selectedValues.selectedWindshieldReplaceOptions
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@ import { mount } from '@vue/test-utils';
|
|||
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||
import { queryStrings } from '@/constants/query-strings';
|
||||
import { GaActions } from '@/constants/analytics';
|
||||
import VehicleLookup from './vehicle-lookup.vue';
|
||||
import {vinLookupMethodSelections} from '@/constants/vin-lookup-methods';
|
||||
import { vinLookupMethodSelections } from '@/constants/vin-lookup-methods';
|
||||
import { useMainStore } from '@/store';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { mapStores } from 'pinia';
|
||||
|
|
@ -12,6 +11,7 @@ import { defineRule } from 'vee-validate';
|
|||
import { errorMessages } from '@/constants/error-messages';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import VehicleLookup from './vehicle-lookup';
|
||||
|
||||
const pinia = createTestingPinia();
|
||||
useMainStore(pinia);
|
||||
|
|
@ -59,7 +59,7 @@ function setupMocks() {
|
|||
navigate: jest.fn()
|
||||
};
|
||||
|
||||
const mockIsVinbyAddressPermissibleToBeFalse={
|
||||
const mockIsVinbyAddressPermissibleToBeFalse = {
|
||||
IsVinbyAddressPermissible: false
|
||||
};
|
||||
|
||||
|
|
@ -126,7 +126,7 @@ function setupMocks() {
|
|||
|
||||
describe('vehicle-lookup.vue', () => {
|
||||
test('IsVinbyAddressPermissible to be false', () => {
|
||||
const { wrapper,mockIsVinbyAddressPermissibleToBeFalse } = setupMocks();
|
||||
const { wrapper, mockIsVinbyAddressPermissibleToBeFalse } = setupMocks();
|
||||
|
||||
const vinLookupMethodsWrapper = wrapper.findComponent({ name: 'vin-lookup-methods' });
|
||||
// Not using initializeComponent() because it doesn't trigger reactivity in test.
|
||||
|
|
@ -139,7 +139,8 @@ describe('vehicle-lookup.vue', () => {
|
|||
answersFromCms: Answers
|
||||
});
|
||||
|
||||
const lookupByAddressOptionLabel = wrapper.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-HomeAddress"]');
|
||||
const lookupByAddressOptionLabel = wrapper
|
||||
.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-HomeAddress"]');
|
||||
expect(lookupByAddressOptionLabel.exists()).toBe(false);
|
||||
});
|
||||
|
||||
|
|
@ -165,7 +166,8 @@ describe('vehicle-lookup.vue', () => {
|
|||
answersFromCms: vinLookupMethodsMockData.Answers
|
||||
});
|
||||
|
||||
const lookupByManualVinOptionLabel = wrapper.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-ManualVin"]');
|
||||
const lookupByManualVinOptionLabel = wrapper
|
||||
.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-ManualVin"]');
|
||||
await lookupByManualVinOptionLabel.trigger('mousedown');
|
||||
|
||||
const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
|
||||
|
|
@ -193,7 +195,8 @@ describe('vehicle-lookup.vue', () => {
|
|||
|
||||
useMainStore().updateVehicleVin = jest.fn();
|
||||
|
||||
const lookupByManualVinOptionLabel = wrapper.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-ManualVin"]');
|
||||
const lookupByManualVinOptionLabel = wrapper
|
||||
.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-ManualVin"]');
|
||||
await lookupByManualVinOptionLabel.trigger('mousedown');
|
||||
|
||||
const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
|
||||
|
|
@ -218,7 +221,8 @@ describe('vehicle-lookup.vue', () => {
|
|||
answersFromCms: vinLookupMethodsMockData.Answers
|
||||
});
|
||||
|
||||
const lookupByLicensePlateOptionLabel = wrapper.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-LicensePlate"]');
|
||||
const lookupByLicensePlateOptionLabel = wrapper
|
||||
.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-LicensePlate"]');
|
||||
await lookupByLicensePlateOptionLabel.trigger('mousedown');
|
||||
|
||||
const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
|
||||
|
|
@ -243,7 +247,8 @@ describe('vehicle-lookup.vue', () => {
|
|||
answersFromCms: vinLookupMethodsMockData.Answers
|
||||
});
|
||||
|
||||
const lookupByAddressOptionLabel = wrapper.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-HomeAddress"]');
|
||||
const lookupByAddressOptionLabel = wrapper
|
||||
.find('[data-test-id="vin-lookup-methods-button-question"] label[for="VinLookupMethods-HomeAddress"]');
|
||||
await lookupByAddressOptionLabel.trigger('mousedown');
|
||||
|
||||
const continueButton = wrapper.get('[data-test-id="site-footer-main-button"]');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit">
|
||||
<Form
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
|
|
@ -8,10 +10,24 @@
|
|||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<VehicleBanner class="mt-2 mb-4" cms-widget-name="VehicleBannerWidget" :display-generic-vehicle-image="false" />
|
||||
<SiteSubHeader cms-widget-name="SiteSubHeaderWidget" class="mt-5 mb-2" />
|
||||
<VinLookupMethods v-model="selectedVinLookupMethod" cms-widget-name="VINLookupMethod" group-name="VinLookupMethods" ref="VinLookupMethods" />
|
||||
<SiteFooter cms-widget-name="SiteFooterWidget" :is-forward-action-disabled="isForwardActionDisabled" @back-clicked="backButtonAction" @forward-clicked="forwardButtonAction" class="mt-5"/>
|
||||
<VehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<SiteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-5 mb-2" />
|
||||
<VinLookupMethods
|
||||
ref="VinLookupMethods"
|
||||
v-model="selectedVinLookupMethod"
|
||||
cmsWidgetName="VINLookupMethod"
|
||||
groupName="VinLookupMethods" />
|
||||
<SiteFooter
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
class="mt-5"
|
||||
@back-clicked="backButtonAction"
|
||||
@forward-clicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -27,20 +43,20 @@ import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
|||
import { settleAllPromises } from '@/helpers/layout-helper';
|
||||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin';
|
||||
import {vinLookupMethodSelections} from '@/constants/vin-lookup-methods';
|
||||
import { vinLookupMethodSelections } from '@/constants/vin-lookup-methods';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
// Import Component
|
||||
import SiteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import SiteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import SiteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import VehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
||||
import VinLookupMethods from './vin-lookup-methods/vin-lookup-methods.vue';
|
||||
import SiteFooter from '@/iss-components/site-footer/site-footer';
|
||||
import SiteHeader from '@/iss-components/site-header/site-header';
|
||||
import SiteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
|
||||
import VehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner';
|
||||
import VinLookupMethods from './vin-lookup-methods/vin-lookup-methods';
|
||||
|
||||
export default {
|
||||
name: 'vehicle-lookup',
|
||||
mixins: [BaseFormMixin],
|
||||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
SiteFooter,
|
||||
SiteHeader,
|
||||
|
|
@ -48,11 +64,7 @@ export default {
|
|||
VehicleBanner,
|
||||
VinLookupMethods
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedVinLookupMethod: null
|
||||
};
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
|
|
@ -71,6 +83,11 @@ export default {
|
|||
vm.$refs.VinLookupMethods.initializeComponent();
|
||||
});
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedVinLookupMethod: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return this.selectedVinLookupMethod === null;
|
||||
|
|
|
|||
|
|
@ -2,12 +2,11 @@
|
|||
<ButtonQuestion
|
||||
v-model="selectedValue"
|
||||
:answers="answersFromCms"
|
||||
button-type-string="listButton"
|
||||
:question-text="questionTextFromCms"
|
||||
is-required
|
||||
:validation-rules="rules.optionRequired"
|
||||
data-test-id="vin-lookup-methods-button-question"
|
||||
/>
|
||||
buttonTypeString="listButton"
|
||||
:questionText="questionTextFromCms"
|
||||
isRequired
|
||||
:validationRules="rules.optionRequired"
|
||||
data-test-id="vin-lookup-methods-button-question" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -19,18 +18,12 @@ import { settleAllPromises } from '@/helpers/layout-helper';
|
|||
import globalRules from '@/constants/global-rules';
|
||||
|
||||
// Import Component
|
||||
import ButtonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import ButtonQuestion from '@/digital-components/button-question/button-question';
|
||||
|
||||
export default {
|
||||
name: 'vin-lookup-methods',
|
||||
data() {
|
||||
return {
|
||||
questionTextFromCms: '',
|
||||
answersFromCms: [],
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
};
|
||||
components: {
|
||||
ButtonQuestion
|
||||
},
|
||||
props: {
|
||||
modelValue: String,
|
||||
|
|
@ -40,8 +33,14 @@ export default {
|
|||
}
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
components: {
|
||||
ButtonQuestion
|
||||
data() {
|
||||
return {
|
||||
questionTextFromCms: '',
|
||||
answersFromCms: [],
|
||||
rules: {
|
||||
optionRequired: globalRules.OPTION_REQUIRED
|
||||
}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
selectedValue: {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass-part-question.vue';
|
||||
import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass-part-question';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
const featureListData = {
|
||||
|
|
@ -31,16 +31,12 @@ describe('glass-part-question.vue', () => {
|
|||
// Act
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
console.log(wrapper.vm.featureListData['Green Tint'][0].Text)
|
||||
console.log(wrapper.vm.featureListData['Green Tint'][0].Text);
|
||||
// Assert
|
||||
expect(Object.keys(wrapper.vm.featureListData).length).toBe(2);
|
||||
expect(wrapper.vm.featureListData['Green Tint'][0].Text).toBe(
|
||||
'heated glass, solar, 1 hole'
|
||||
);
|
||||
expect(wrapper.vm.featureListData['Green Tint'][0].Text).toBe('heated glass, solar, 1 hole');
|
||||
expect(wrapper.vm.featureListData['Green Tint'][0].Name).toBe('DB12209GTYN');
|
||||
expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Text).toBe(
|
||||
'heated glass, solar, 1 hole'
|
||||
);
|
||||
expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Text).toBe('heated glass, solar, 1 hole');
|
||||
expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Name).toBe('DB12209YPYN');
|
||||
});
|
||||
|
||||
|
|
@ -161,8 +157,7 @@ describe('glass-part-question.vue', () => {
|
|||
['Driver', 'Quarter', 'Green Tint', []]
|
||||
];
|
||||
|
||||
test.each(partsForSelectedTintTestCases)(
|
||||
'partsForSelectedTint returns correct parts',
|
||||
test.each(partsForSelectedTintTestCases)('partsForSelectedTint returns correct parts',
|
||||
async (glassLocation, glassName, selectedTint, expectedResults) => {
|
||||
// Arrange
|
||||
const pageData = { partsOrQuestions: [
|
||||
|
|
@ -187,7 +182,7 @@ describe('glass-part-question.vue', () => {
|
|||
{ partNumber: 'Windshield2', color: 'Green Tint' }
|
||||
]
|
||||
}
|
||||
] }
|
||||
] };
|
||||
const { wrapper } = setupMocks({
|
||||
glassLocationProp: glassLocation,
|
||||
glassNameProp: glassName,
|
||||
|
|
@ -196,12 +191,11 @@ describe('glass-part-question.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
await wrapper.setData({ selectedTint: selectedTint });
|
||||
await wrapper.setData({ selectedTint });
|
||||
|
||||
// Assert
|
||||
expect(expectedResults).toEqual(wrapper.vm.partsForSelectedTint);
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
function setupMocks({ glassNameProp, glassLocationProp, colorAnswersProp, modelValueProp, pageData }) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<template>
|
||||
<div class="row">
|
||||
<p class="mb-0 color-question-text">{{ colorQuestionText }}</p>
|
||||
<p class="mb-0 color-question-text">
|
||||
{{ colorQuestionText }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="nested-radio">
|
||||
<div class="row my-2">
|
||||
|
|
@ -14,7 +16,9 @@
|
|||
isRequired
|
||||
:groupName="replaceAllSpaceWithDash(`${glassLocation}-${glassName}`)"
|
||||
:validationRules="tintValidationRules">
|
||||
<div class="row my-2" aria-live="polite">
|
||||
<div
|
||||
class="row my-2"
|
||||
aria-live="polite">
|
||||
<div class="col">
|
||||
<buttonQuestion
|
||||
id="glass-part-question"
|
||||
|
|
@ -50,15 +54,10 @@ import { errorMessages } from '@/constants/error-messages';
|
|||
|
||||
export default {
|
||||
name: 'glass-part-question',
|
||||
emits: ['update:modelValue'],
|
||||
inheritAttrs: false,
|
||||
data() {
|
||||
return {
|
||||
glassColorQuestion: '',
|
||||
glassFeatureQuestion: '',
|
||||
selectedTint: ''
|
||||
};
|
||||
components: {
|
||||
buttonQuestion
|
||||
},
|
||||
inheritAttrs: false,
|
||||
props: {
|
||||
glassName: String,
|
||||
glassLocation: String,
|
||||
|
|
@ -69,11 +68,13 @@ export default {
|
|||
default: () => []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.LoadPreselectedValues();
|
||||
},
|
||||
components: {
|
||||
buttonQuestion
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
glassColorQuestion: '',
|
||||
glassFeatureQuestion: '',
|
||||
selectedTint: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tintValidationRules() {
|
||||
|
|
@ -90,23 +91,19 @@ export default {
|
|||
return validationRuleName;
|
||||
},
|
||||
colorQuestionText() {
|
||||
return getCustomTransformValue(
|
||||
this.glassColorQuestion,
|
||||
`${this.glassLocation} ${this.glassName}`
|
||||
);
|
||||
return getCustomTransformValue(this.glassColorQuestion,
|
||||
`${this.glassLocation} ${this.glassName}`);
|
||||
},
|
||||
|
||||
tintSelectionOptions() {
|
||||
let tintOptions = [];
|
||||
const tintOptions = [];
|
||||
|
||||
Object.keys(this.featureListData).forEach((tintOption) => {
|
||||
tintOptions.push({
|
||||
value: tintOption,
|
||||
buttonLabel: tintOption,
|
||||
buttonImage: require(`@/assets/img/tints/${this.getTintSourceImage(
|
||||
this.glassLocation,
|
||||
tintOption
|
||||
)}`),
|
||||
buttonImage: require(`@/assets/img/tints/${this.getTintSourceImage(this.glassLocation,
|
||||
tintOption)}`)
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -118,19 +115,18 @@ export default {
|
|||
return this.modelValue?.partNumber;
|
||||
},
|
||||
set(newValue) {
|
||||
const part = this.partsForSelectedTint.filter((part) => part.partNumber == newValue?.value)[0];
|
||||
const part = this.partsForSelectedTint
|
||||
.filter((partItem) => partItem.partNumber === newValue?.value)[0];
|
||||
this.$emit('update:modelValue', part);
|
||||
}
|
||||
},
|
||||
|
||||
partsForSelectedTint() {
|
||||
const matchingGlass = this.PartDataFromApi.partsOrQuestions?.filter(
|
||||
(dataForGlassLocationAndName) =>
|
||||
dataForGlassLocationAndName.glassName == this.glassName &&
|
||||
dataForGlassLocationAndName.glassLocation == this.glassLocation
|
||||
);
|
||||
const matchingGlassParts = matchingGlass?.length == 1 ? matchingGlass[0].parts : [];
|
||||
return matchingGlassParts.filter((part) => part.color == this.selectedTint) ?? [];
|
||||
const matchingGlass = this.PartDataFromApi.partsOrQuestions?.filter((dataForGlassLocationAndName) =>
|
||||
dataForGlassLocationAndName.glassName === this.glassName
|
||||
&& dataForGlassLocationAndName.glassLocation === this.glassLocation);
|
||||
const matchingGlassParts = matchingGlass?.length === 1 ? matchingGlass[0].parts : [];
|
||||
return matchingGlassParts.filter((part) => part.color === this.selectedTint) ?? [];
|
||||
},
|
||||
|
||||
// Creates a map of the feature list data in the correct Name/Value
|
||||
|
|
@ -142,9 +138,9 @@ export default {
|
|||
arr[itemColor] = arr[itemColor] || [];
|
||||
|
||||
// Map the data to Name/Text object for ButtonQuestion
|
||||
const mappedItem = item.FeatureAnswers.reduce((featureArr, item) => {
|
||||
featureArr['Text'] = item.FeatureAnswerText; // Display to User
|
||||
featureArr['Name'] = item.PartNumber; // Backing Value
|
||||
const mappedItem = item.FeatureAnswers.reduce((featureArr, it) => {
|
||||
featureArr.Text = it.FeatureAnswerText; // Display to User
|
||||
featureArr.Name = it.PartNumber; // Backing Value
|
||||
|
||||
return featureArr;
|
||||
}, {});
|
||||
|
|
@ -161,6 +157,14 @@ export default {
|
|||
return this.mainStore.pageData(this.$route.query.issPage) ?? {};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedTint() {
|
||||
this.AutoSelectIfSinglePart();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.LoadPreselectedValues();
|
||||
},
|
||||
methods: {
|
||||
// Initialize the component data
|
||||
initializeComponent(cmsContent) {
|
||||
|
|
@ -173,7 +177,7 @@ export default {
|
|||
getTintSourceImage(glassLocation, tintColor) {
|
||||
const tintSourceObject = getTintImage(glassLocation, tintColor);
|
||||
|
||||
if (tintSourceObject === undefined || tintSourceObject.src == undefined) {
|
||||
if (tintSourceObject === undefined || !tintSourceObject.src) {
|
||||
return '';
|
||||
}
|
||||
|
||||
|
|
@ -183,12 +187,12 @@ export default {
|
|||
AutoSelectIfSinglePart() {
|
||||
if (this.partsForSelectedTint?.length > 0) {
|
||||
// Check if only a single part is present for the tint and set the v-model if it is.
|
||||
if (this.partsForSelectedTint?.length == 1) {
|
||||
if (this.partsForSelectedTint?.length === 1) {
|
||||
this.selectedPartNumber = { value: this.partsForSelectedTint[0].partNumber };
|
||||
|
||||
// //select element with matching partNumber
|
||||
this.$nextTick(() => {
|
||||
const radioInput = document.querySelector('input[value=' + this.selectedPartNumber + ']');
|
||||
const radioInput = document.querySelector(`input[value=${this.selectedPartNumber}]`);
|
||||
// Fire a click event on the input so the field is updated
|
||||
radioInput?.click();
|
||||
});
|
||||
|
|
@ -211,16 +215,11 @@ export default {
|
|||
replaceAllSpaceWithDash(str) {
|
||||
return String(str).replaceAll(' ', '-');
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedTint() {
|
||||
this.AutoSelectIfSinglePart();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.nested-radio {
|
||||
.ui-radio {
|
||||
flex-direction: column;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Components
|
||||
import vehicleParts from '@/layouts/vehicle-parts/vehicle-parts.vue';
|
||||
import vehicleParts from '@/layouts/vehicle-parts/vehicle-parts';
|
||||
import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass-part-question';
|
||||
|
||||
// Supporting Files
|
||||
|
|
@ -82,12 +82,10 @@ describe('vehicle-parts.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
vehicleParts.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
vehicleParts.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'vehicle-parts' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
wrapper.vm.setCmsContent = jest.fn();
|
||||
|
||||
// Assert
|
||||
|
|
@ -117,14 +115,12 @@ describe('vehicle-parts.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
vehicleParts.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
vehicleParts.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'vehicle-parts' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
|
||||
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||
await nextTick();
|
||||
|
||||
// Assert
|
||||
|
|
@ -151,12 +147,10 @@ describe('vehicle-parts.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
vehicleParts.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
vehicleParts.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'vehicle-parts' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
|
||||
await nextTick();
|
||||
|
||||
|
|
@ -189,20 +183,16 @@ describe('vehicle-parts.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
vehicleParts.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
vehicleParts.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'vehicle-parts' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
|
||||
wrapper.vm.navigateBack();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
wrapper.vm.$route
|
||||
);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
wrapper.vm.$route);
|
||||
});
|
||||
|
||||
test('User did not have part questions > navigateBack triggers a router.navigate change with correct scenario', async () => {
|
||||
|
|
@ -221,20 +211,16 @@ describe('vehicle-parts.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
vehicleParts.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
vehicleParts.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'vehicle-parts' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
|
||||
wrapper.vm.navigateBack();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
wrapper.vm.$route
|
||||
);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS,
|
||||
wrapper.vm.$route);
|
||||
});
|
||||
|
||||
test('ForwardButtonAction triggers a router.navigate change if there are child part questions', async () => {
|
||||
|
|
@ -296,22 +282,20 @@ describe('vehicle-parts.vue', () => {
|
|||
});
|
||||
|
||||
wrapper.setData({
|
||||
selectedGlassParts: { 'Rear-Stationary': { partNumber: 'FW03861GTYN' } },
|
||||
selectedGlassParts: { 'Rear-Stationary': { partNumber: 'FW03861GTYN' } }
|
||||
});
|
||||
|
||||
// Act
|
||||
vehicleParts.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
vehicleParts.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'vehicle-parts' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith('CLICKED_FORWARD_WITH_MOLDING_QUESTIONS', {'query': {'issPage': 'vehicle-parts'}}, {}, {}, expect.anything());
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith('CLICKED_FORWARD_WITH_MOLDING_QUESTIONS', { query: { issPage: 'vehicle-parts' } }, {}, {}, expect.anything());
|
||||
});
|
||||
|
||||
test('ForwardButtonAction triggers a router.navigate change if there are capability questions', async () => {
|
||||
|
|
@ -363,18 +347,16 @@ describe('vehicle-parts.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
vehicleParts.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
vehicleParts.beforeRouteEnter.call(wrapper.vm,
|
||||
{ query: { issPage: 'vehicle-parts' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
(c) => c(wrapper.vm));
|
||||
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith('CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS', {'query': {'issPage': 'vehicle-parts'}}, {}, {}, expect.anything());
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith('CLICKED_FORWARD_WITH_CAPABILITY_QUESTIONS', { query: { issPage: 'vehicle-parts' } }, {}, {}, expect.anything());
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -401,8 +383,8 @@ function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {}
|
|||
};
|
||||
|
||||
const store = useMainStore();
|
||||
let actionResult = [];
|
||||
store.getCapabilityQuestions.mockImplementation(() => Promise.resolve({data: actionResult,}));
|
||||
const actionResult = [];
|
||||
store.getCapabilityQuestions.mockImplementation(() => Promise.resolve({ data: actionResult }));
|
||||
|
||||
const apiPromise = Promise.resolve(apiResponses);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
||||
<Form
|
||||
ref="theForm"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
|
|
@ -9,24 +12,28 @@
|
|||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
ref="vehicleBanner"
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader ref="siteSubHeader" cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<div class="prevent-squish my-5">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<alert
|
||||
id="vehicle-parts-alert"
|
||||
class="rounded border-0 shadow-sm"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="AlertWidget"
|
||||
:isDismissible="false"
|
||||
id="vehicle-parts-alert" />
|
||||
:isDismissible="false" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
||||
<div
|
||||
v-for="(item, i) in PartsOrQuestions"
|
||||
:key="i">
|
||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||
<hr v-if="i > 0" />
|
||||
<glassPartQuestion
|
||||
|
|
@ -38,9 +45,9 @@
|
|||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
ref="siteFooter"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
@backClicked="navigateBack"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
|
|
@ -73,6 +80,16 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
|||
|
||||
export default {
|
||||
name: 'vehicle-parts',
|
||||
components: {
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
glassPartQuestion,
|
||||
siteHeader,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
siteFooter,
|
||||
alert
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
|
|
@ -96,8 +113,7 @@ export default {
|
|||
vm.$refs[c][0].initializeComponent({
|
||||
ColorQuestionWidget: resultMap.cmsContent.ColorQuestionWidget,
|
||||
FeatureQuestionWidget: resultMap.cmsContent.FeatureQuestionWidget
|
||||
})
|
||||
);
|
||||
}));
|
||||
});
|
||||
},
|
||||
data() {
|
||||
|
|
@ -109,12 +125,12 @@ export default {
|
|||
},
|
||||
computed: {
|
||||
isForwardActionDisabled() {
|
||||
return this.selectedGlassPartNumbers?.length !== this.PartsFromApi.partsOrQuestions?.length
|
||||
return this.selectedGlassPartNumbers?.length !== this.PartsFromApi.partsOrQuestions?.length;
|
||||
},
|
||||
selectedGlassPartNumbers() {
|
||||
// Compile all selected parts from the page.
|
||||
const numberArray = [];
|
||||
for (let glassPart of Object.values(this.selectedGlassParts)) {
|
||||
for (const glassPart of Object.values(this.selectedGlassParts)) {
|
||||
if (glassPart?.partNumber) {
|
||||
numberArray.push(glassPart.partNumber);
|
||||
}
|
||||
|
|
@ -125,25 +141,23 @@ export default {
|
|||
const partsData = this.PartsFromApi;
|
||||
|
||||
// Map API result data, to vehicle-parts data structure
|
||||
const mappedData = partsData.partsOrQuestions?.map((g) => {
|
||||
return {
|
||||
glassName: g.glassName,
|
||||
glassLocation: g.glassLocation,
|
||||
colorAnswers: g.parts?.reduce((arr, p) => {
|
||||
arr.push({
|
||||
ColorAnswerText: p.color,
|
||||
FeatureAnswers: [
|
||||
{
|
||||
FeatureAnswerText:
|
||||
const mappedData = partsData.partsOrQuestions?.map((g) => ({
|
||||
glassName: g.glassName,
|
||||
glassLocation: g.glassLocation,
|
||||
colorAnswers: g.parts?.reduce((arr, p) => {
|
||||
arr.push({
|
||||
ColorAnswerText: p.color,
|
||||
FeatureAnswers: [
|
||||
{
|
||||
FeatureAnswerText:
|
||||
p.description === '' ? p.color : p.description,
|
||||
PartNumber: p.partNumber
|
||||
}
|
||||
]
|
||||
});
|
||||
return arr;
|
||||
}, [])
|
||||
};
|
||||
});
|
||||
PartNumber: p.partNumber
|
||||
}
|
||||
]
|
||||
});
|
||||
return arr;
|
||||
}, [])
|
||||
}));
|
||||
|
||||
return mappedData;
|
||||
},
|
||||
|
|
@ -156,26 +170,27 @@ export default {
|
|||
return 'partQuestion';
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.LoadInitialPartsData();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
// Check if isRepair is populated and if the pageData we need is here (Parts data)
|
||||
return (
|
||||
this.mainStore.damage.isRepair != null &&
|
||||
this.mainStore.pageData(issPageValues.VEHICLE_PARTS) &&
|
||||
Object.keys(this.mainStore.pageData(issPageValues.VEHICLE_PARTS)).length !== 0
|
||||
this.mainStore.damage.isRepair != null
|
||||
&& this.mainStore.pageData(issPageValues.VEHICLE_PARTS)
|
||||
&& Object.keys(this.mainStore.pageData(issPageValues.VEHICLE_PARTS)).length !== 0
|
||||
);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
const matchedParts = [];
|
||||
|
||||
// Match them to the parts from the API.
|
||||
for (let [key, value] of Object.entries(this.PartsFromApi.partsOrQuestions)) {
|
||||
for (let [partKey, partValue] of Object.entries(value.parts)) {
|
||||
for (const [key, value] of Object.entries(this.PartsFromApi.partsOrQuestions)) {
|
||||
for (const [partKey, partValue] of Object.entries(value.parts)) {
|
||||
const currentPart = this.PartsFromApi.partsOrQuestions[key].parts[partKey];
|
||||
|
||||
const isMatched = this.selectedGlassPartNumbers.some(
|
||||
(p) => p === currentPart.partNumber
|
||||
);
|
||||
const isMatched = this.selectedGlassPartNumbers.some((p) => p === currentPart.partNumber);
|
||||
|
||||
if (isMatched) {
|
||||
matchedParts.push({
|
||||
|
|
@ -197,39 +212,27 @@ export default {
|
|||
|
||||
LoadInitialPartsData() {
|
||||
const partsData = this.PartsFromApi;
|
||||
this.alreadyPopulatedPartsData =
|
||||
this.mainStore.lineItems.glassParts === null
|
||||
? []
|
||||
: this.mainStore.lineItems.glassParts;
|
||||
this.alreadyPopulatedPartsData
|
||||
= this.mainStore.lineItems.glassParts === null
|
||||
? []
|
||||
: this.mainStore.lineItems.glassParts;
|
||||
|
||||
partsData.partsOrQuestions.map((g) => {
|
||||
// If the part is already populated, use the value from the store and populate the v-model.
|
||||
Object.keys(this.alreadyPopulatedPartsData).forEach((key) => {
|
||||
const partNumber = this.alreadyPopulatedPartsData[key].partNumber;
|
||||
const { partNumber } = this.alreadyPopulatedPartsData[key];
|
||||
g.parts.forEach((p) => {
|
||||
if (p.partNumber === partNumber) {
|
||||
this.selectedGlassParts[g.glassLocation + '-' + g.glassName] = p;
|
||||
this.selectedGlassParts[`${g.glassLocation}-${g.glassName}`] = p;
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.LoadInitialPartsData();
|
||||
},
|
||||
components: {
|
||||
Form,
|
||||
glassPartQuestion,
|
||||
siteHeader,
|
||||
vehicleBanner,
|
||||
siteSubHeader,
|
||||
siteFooter,
|
||||
alert
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
#vehicle-parts-alert {
|
||||
.alert-heading {
|
||||
margin-top: 0.25rem !important;
|
||||
|
|
|
|||
|
|
@ -1,32 +1,32 @@
|
|||
<template>
|
||||
<dropdownQuestion
|
||||
v-model="selectedValue"
|
||||
:options="values"
|
||||
disableAutoFill
|
||||
placeHolderText="Select an option"
|
||||
v-model="selectedValue"
|
||||
:isDisabled="!values.length"
|
||||
/>
|
||||
:isDisabled="!values.length" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question';
|
||||
|
||||
export default {
|
||||
name: 'vehicle-question',
|
||||
components: {
|
||||
dropdownQuestion
|
||||
},
|
||||
props: {
|
||||
modelValue: String,
|
||||
updateValues: Function
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
values: [],
|
||||
selectedIndex: null
|
||||
};
|
||||
},
|
||||
props: {
|
||||
modelValue: String,
|
||||
updateValues: Function,
|
||||
},
|
||||
components: {
|
||||
dropdownQuestion
|
||||
},
|
||||
computed: {
|
||||
selectedValue: {
|
||||
get() {
|
||||
|
|
@ -43,7 +43,7 @@ export default {
|
|||
async getNewValues() {
|
||||
const results = await this.updateValues();
|
||||
this.values = results?.data;
|
||||
if (this.values.length == 1) {
|
||||
if (this.values.length === 1) {
|
||||
this.selectedValue = 0;
|
||||
} else {
|
||||
this.selectedValue = null;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles position-relative">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
|
|
@ -12,61 +16,54 @@
|
|||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="siteSubHeader"
|
||||
justification="center"
|
||||
darkGraySubText
|
||||
/>
|
||||
darkGraySubText />
|
||||
|
||||
<vehicleQuestion
|
||||
ref="vehicleYearQuestion"
|
||||
class="mb-2 mt-4"
|
||||
v-model="selectedYear"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleYearQuestion"
|
||||
:updateValues="updateYearValues"
|
||||
validationRules="year-required"
|
||||
inputId="yearQuestionField"
|
||||
/>
|
||||
inputId="yearQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleMakeQuestion"
|
||||
class="mb-2 mt-4"
|
||||
v-model="selectedMake"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleMakeQuestion"
|
||||
:updateValues="updateMakeValues"
|
||||
validationRules="make-required"
|
||||
inputId="makeQuestionField"
|
||||
/>
|
||||
inputId="makeQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleModelQuestion"
|
||||
class="mb-2 mt-4"
|
||||
v-model="selectedModel"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleModelQuestion"
|
||||
:updateValues="updateModelValues"
|
||||
validationRules="model-required"
|
||||
inputId="modelQuestionField"
|
||||
/>
|
||||
inputId="modelQuestionField" />
|
||||
<vehicleQuestion
|
||||
ref="vehicleStyleQuestion"
|
||||
class="mb-2 mt-4"
|
||||
v-model="selectedStyle"
|
||||
class="mb-2 mt-4"
|
||||
cmsWidgetName="VehicleStyleQuestion"
|
||||
:updateValues="updateStyleValues"
|
||||
validationRules="style-required"
|
||||
inputId="styleQuestionField"
|
||||
/>
|
||||
inputId="styleQuestionField" />
|
||||
|
||||
<vehicleBanner
|
||||
ref="banner"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="displayGeneric"
|
||||
class="mt-5 mb-3"
|
||||
ref="banner"
|
||||
/>
|
||||
class="mt-5 mb-3" />
|
||||
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@back-clicked="backButtonAction"
|
||||
ref="siteFooter"
|
||||
/>
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@back-clicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -83,14 +80,14 @@ import siteHeader from '@/iss-components/site-header/site-header';
|
|||
import siteFooter from '@/iss-components/site-footer/site-footer';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner';
|
||||
import vehicleQuestion from '@/layouts/vehicle-selection/vehicle-question/vehicle-question.vue';
|
||||
import vehicleQuestion from '@/layouts/vehicle-selection/vehicle-question/vehicle-question';
|
||||
import { useMainStore } from '@/store';
|
||||
|
||||
// Supporting files
|
||||
import baseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import { settleAllPromises } from '@/helpers/layout-helper';
|
||||
import { Form, defineRule, useForm } from 'vee-validate';
|
||||
import { Form, defineRule } from 'vee-validate';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import { errorMessages } from '@/constants/error-messages';
|
||||
|
||||
|
|
@ -102,22 +99,16 @@ defineRule('style-required', required(errorMessages.STYLE_REQUIRED));
|
|||
|
||||
export default {
|
||||
name: 'vehicle-selection',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
vehicleBanner,
|
||||
siteFooter,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
vehicleQuestion
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
data() {
|
||||
return {
|
||||
selectedYear: null,
|
||||
selectedMake: null,
|
||||
selectedModel: null,
|
||||
selectedStyle: null
|
||||
};
|
||||
},
|
||||
props: {
|
||||
cmsWidgetName:String,
|
||||
validationRules:String
|
||||
},
|
||||
mounted() {
|
||||
this.$refs['vehicleYearQuestion'].getNewValues();
|
||||
},
|
||||
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
|
|
@ -131,34 +122,51 @@ export default {
|
|||
}
|
||||
];
|
||||
|
||||
let resultMap = await settleAllPromises(promiseResultMap);
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
validationRules: String
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedYear: null,
|
||||
selectedMake: null,
|
||||
selectedModel: null,
|
||||
selectedStyle: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
displayGeneric() {
|
||||
return !this.selectedStyle;
|
||||
}
|
||||
},
|
||||
|
||||
watch: {
|
||||
selectedYear(value) {
|
||||
this.mainStore.updateVehicleYear(value);
|
||||
this.$refs['vehicleMakeQuestion'].clearValues();
|
||||
this.$refs.vehicleMakeQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs['vehicleMakeQuestion'].getNewValues();
|
||||
this.$refs.vehicleMakeQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
selectedMake(value) {
|
||||
this.mainStore.updateVehicleMake(value);
|
||||
this.$refs['vehicleModelQuestion'].clearValues();
|
||||
this.$refs.vehicleModelQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs['vehicleModelQuestion'].getNewValues();
|
||||
this.$refs.vehicleModelQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
selectedModel(value) {
|
||||
this.mainStore.updateVehicleModel(value);
|
||||
this.$refs['vehicleStyleQuestion'].clearValues();
|
||||
this.$refs.vehicleStyleQuestion.clearValues();
|
||||
if (value) {
|
||||
this.$refs['vehicleStyleQuestion'].getNewValues();
|
||||
this.$refs.vehicleStyleQuestion.getNewValues();
|
||||
}
|
||||
},
|
||||
selectedStyle(value) {
|
||||
|
|
@ -166,6 +174,9 @@ export default {
|
|||
this.mainStore.setVehicle();
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.$refs.vehicleYearQuestion.getNewValues();
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
return true;
|
||||
|
|
@ -179,10 +190,8 @@ export default {
|
|||
|
||||
navigateForward() {
|
||||
this.mainStore.setVehicle().then(() => {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route
|
||||
);
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD,
|
||||
this.$route);
|
||||
});
|
||||
},
|
||||
async updateYearValues() {
|
||||
|
|
@ -197,24 +206,11 @@ export default {
|
|||
async updateStyleValues() {
|
||||
return await this.mainStore.getVehicleStyles();
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
displayGeneric() {
|
||||
return !this.selectedStyle;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
vehicleBanner,
|
||||
siteFooter,
|
||||
Form,
|
||||
vehicleQuestion
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.select-car-form {
|
||||
margin-left: .75rem;
|
||||
margin-right: .75rem;
|
||||
|
|
|
|||
|
|
@ -4,8 +4,8 @@ import userEvent from '@testing-library/user-event';
|
|||
import '@testing-library/jest-dom';
|
||||
import { issPageValues } from '@/router/router-constants/issPage-values';
|
||||
import { queryStrings } from '@/constants/query-strings';
|
||||
import { GaActions } from "@/constants/analytics";
|
||||
import VinLocationInformationComponent from './vin-location-information.vue';
|
||||
import { GaActions } from '@/constants/analytics';
|
||||
import VinLocationInformationComponent from './vin-location-information';
|
||||
|
||||
const mockText = Object.freeze({
|
||||
HEADER: 'Mock Header',
|
||||
|
|
|
|||
|
|
@ -3,35 +3,30 @@
|
|||
<div
|
||||
class="vin-toggle"
|
||||
:class="[isVinLocationDetailVisible ? 'active' : '']"
|
||||
@click="handleClickToggle"
|
||||
>
|
||||
@click="handleClickToggle">
|
||||
<textLink
|
||||
linkType="text"
|
||||
href="#!"
|
||||
:text="textForToggle"
|
||||
/>
|
||||
:text="textForToggle" />
|
||||
</div>
|
||||
<Transition>
|
||||
<div
|
||||
v-show="isVinLocationDetailVisible"
|
||||
id="vin-location-detail-wrapper"
|
||||
class="mt-2"
|
||||
>
|
||||
class="mt-2">
|
||||
<div
|
||||
v-html="vinLocationDetailContent"
|
||||
id="vin-location-detail-content"
|
||||
class="mb-2"
|
||||
/>
|
||||
v-html="vinLocationDetailContent" />
|
||||
<img
|
||||
:src="vinLocationDetailImage"
|
||||
alt="VIN Locations"
|
||||
>
|
||||
alt="VIN Locations">
|
||||
</div>
|
||||
</Transition>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||
import textLink from '@/ux-components/text-link/text-link';
|
||||
|
||||
export default {
|
||||
name: 'vin-location-information',
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
<template>
|
||||
<alert
|
||||
id="perfect-match-alert"
|
||||
alertClass="alert-success"
|
||||
cmsWidgetName="AlertPerfectMatchInsuranceNotVerified"
|
||||
:manualCopy="body"
|
||||
id="perfect-match-alert"
|
||||
aria-label="perfect-match-alert"
|
||||
/>
|
||||
aria-label="perfect-match-alert" />
|
||||
</template>
|
||||
<script>
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import alert from '@/ux-components/alert/alert';
|
||||
import { getDamageString } from '@/helpers/damage-helper';
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
|
||||
:manualCopy="body"
|
||||
:manualHeadline="header"
|
||||
aria-label="two-identical-ymm-vehicle-alert"
|
||||
/>
|
||||
aria-label="two-identical-ymm-vehicle-alert" />
|
||||
</template>
|
||||
<script>
|
||||
import { getDamageString } from '@/helpers/damage-helper';
|
||||
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import alert from '@/ux-components/alert/alert';
|
||||
|
||||
export default {
|
||||
name: 'two-identical-ymm-vehicle-alert',
|
||||
|
|
|
|||
|
|
@ -1,13 +1,12 @@
|
|||
<template>
|
||||
<alert
|
||||
id="vehicle-not-found-alert"
|
||||
alertClass="alert-danger"
|
||||
cmsWidgetName="AlertVinNotFoundWidget"
|
||||
id="vehicle-not-found-alert"
|
||||
aria-label="vehicle-not-found-alert"
|
||||
/>
|
||||
aria-label="vehicle-not-found-alert" />
|
||||
</template>
|
||||
<script>
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import alert from '@/ux-components/alert/alert';
|
||||
|
||||
export default {
|
||||
name: 'vehicle-not-found-alert',
|
||||
|
|
|
|||
|
|
@ -4,13 +4,12 @@
|
|||
cmsWidgetName="AlertMatchedDifferentVehicleWidget"
|
||||
:manualCopy="body"
|
||||
:manualHeadline="header"
|
||||
aria-label="vehicle-not-matched-alert"
|
||||
/>
|
||||
aria-label="vehicle-not-matched-alert" />
|
||||
</template>
|
||||
<script>
|
||||
import { getDamageString } from '@/helpers/damage-helper';
|
||||
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import alert from '@/ux-components/alert/alert';
|
||||
|
||||
export default {
|
||||
name: 'vehicle-not-matched-alert',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import vehicleLookupAlertTypes from '@/constants/vehicle-lookup-alert-types';
|
|||
import { RouterLinkStub } from '@vue/test-utils';
|
||||
import { render } from '@testing-library/vue';
|
||||
import '@testing-library/jest-dom';
|
||||
import VinLookupAlertsComponent from './vin-lookup-alerts.vue';
|
||||
import VinLookupAlertsComponent from './vin-lookup-alerts';
|
||||
|
||||
jest.mock('@/helpers/damage-helper');
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ const mountOptions = {
|
|||
methods: {
|
||||
getCmsContent: jest.fn(() => ''),
|
||||
getFooterInfoBoxHeight: jest.fn(() => 80),
|
||||
cssClassNameForCmsWidget: jest.fn(() => 'widget-name-mock-class'),
|
||||
cssClassNameForCmsWidget: jest.fn(() => 'widget-name-mock-class')
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,28 +1,23 @@
|
|||
<template>
|
||||
<div
|
||||
id="vin-lookup-alerts-wrapper"
|
||||
:class="wrapperCssClass"
|
||||
>
|
||||
:class="wrapperCssClass">
|
||||
<vehicleNotFoundAlert
|
||||
v-if="isVehicleNotFoundVisible"
|
||||
/>
|
||||
v-if="isVehicleNotFoundVisible" />
|
||||
<twoIdenticalYMMVehicleAlert
|
||||
v-if="isTwoIdenticalYMMVehicleFoundVisible"
|
||||
/>
|
||||
v-if="isTwoIdenticalYMMVehicleFoundVisible" />
|
||||
<vehicleNotMatchedAlert
|
||||
v-else-if="isVehicleNotMatchedVisible"
|
||||
/>
|
||||
v-else-if="isVehicleNotMatchedVisible" />
|
||||
<perfectMatchAlert
|
||||
v-else-if="isPerfectMatchVisible"
|
||||
/>
|
||||
v-else-if="isPerfectMatchVisible" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import vehicleLookupAlertTypes from '@/constants/vehicle-lookup-alert-types';
|
||||
import vehicleNotFoundAlert from '@/layouts/vin-lookup/vin-lookup-alerts/vehicle-not-found-alert/vehicle-not-found-alert';
|
||||
import vehicleNotMatchedAlert from '@/layouts/vin-lookup/vin-lookup-alerts/vehicle-not-matched-alert/vehicle-not-matched-alert';
|
||||
import twoIdenticalYMMVehicleAlert from '@/layouts/vin-lookup/vin-lookup-alerts/two-identical-ymm-vehicle-alert/two-identical-ymm-vehicle-alert'
|
||||
import perfectMatchAlert from '@/layouts/vin-lookup/vin-lookup-alerts//perfect-match-alert/perfect-match-alert.vue';
|
||||
import twoIdenticalYMMVehicleAlert from '@/layouts/vin-lookup/vin-lookup-alerts/two-identical-ymm-vehicle-alert/two-identical-ymm-vehicle-alert';
|
||||
import perfectMatchAlert from '@/layouts/vin-lookup/vin-lookup-alerts//perfect-match-alert/perfect-match-alert';
|
||||
|
||||
export default {
|
||||
name: 'vin-lookup-alerts',
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ import { GaActions } from '@/constants/analytics';
|
|||
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||
import { routerParams } from '@/router/router-params';
|
||||
import { useMainStore } from '@/store';
|
||||
import VinLookupComponent from './vin-lookup.vue';
|
||||
import VinLookupComponent from './vin-lookup';
|
||||
|
||||
const continueButtonQuerySelector = '[data-test-id="site-footer-main-button"]';
|
||||
const errorMessageWrapperElSelector = '#vin-question-wrapper .form-test-error';
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
|
|
@ -8,12 +12,27 @@
|
|||
<div class="row px-3">
|
||||
<div class="col">
|
||||
<div class="select-car-form rounded">
|
||||
<vehicleBanner class="mt-2 mb-4" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
|
||||
<vehicleBanner
|
||||
class="mt-2 mb-4"
|
||||
cmsWidgetName="VehicleBannerWidget"
|
||||
:displayGenericVehicleImage="false" />
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<vinLookupAlerts class="mt-5" :activeAlertType="activeVehicleLookupAlertType" />
|
||||
<vinQuestion v-model="vin" :mask="vinMask" :isDisabled="vinPopulatedOnPageLoad" textPosition="left" />
|
||||
<vinLookupAlerts
|
||||
class="mt-5"
|
||||
:activeAlertType="activeVehicleLookupAlertType" />
|
||||
<vinQuestion
|
||||
v-model="vin"
|
||||
:mask="vinMask"
|
||||
:isDisabled="vinPopulatedOnPageLoad"
|
||||
textPosition="left" />
|
||||
<vinLocationInformation />
|
||||
<siteFooter cmsWidgetName="SiteFooterWidget" :isForwardActionDisabled="!meta.valid" @backClicked="backButtonAction" @forwardClicked="forwardButtonAction" ref="siteFooter" class="mt-5" />
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
class="mt-5"
|
||||
@backClicked="backButtonAction"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -37,13 +56,13 @@ import { useMainStore } from '@/store';
|
|||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import { Form } from 'vee-validate';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
|
||||
import vinLocationInformation from './vin-location-information/vin-location-information.vue';
|
||||
import vinLookupAlerts from './vin-lookup-alerts/vin-lookup-alerts.vue';
|
||||
import vinQuestion from './vin-question/vin-question.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer';
|
||||
import siteHeader from '@/iss-components/site-header/site-header';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
|
||||
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner';
|
||||
import vinLocationInformation from './vin-location-information/vin-location-information';
|
||||
import vinLookupAlerts from './vin-lookup-alerts/vin-lookup-alerts';
|
||||
import vinQuestion from './vin-question/vin-question';
|
||||
|
||||
export default {
|
||||
name: 'vin-lookup',
|
||||
|
|
@ -51,6 +70,7 @@ export default {
|
|||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
vehicleBanner,
|
||||
vinLocationInformation,
|
||||
|
|
@ -60,23 +80,7 @@ export default {
|
|||
mixins: [baseFormMixin, vehicleQuestionsMixin],
|
||||
provide() {
|
||||
return {
|
||||
vehicleFromLookup: computed(() => this.vehicleFromLookup),
|
||||
};
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeVehicleLookupAlertType: null,
|
||||
needToLookupVehicle: true,
|
||||
vehicleFromLookup: null,
|
||||
vin: this.getVinFromStore(),
|
||||
forwardButtonCarStyle: '',
|
||||
vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0,
|
||||
bailout: false
|
||||
vehicleFromLookup: computed(() => this.vehicleFromLookup)
|
||||
};
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -96,6 +100,22 @@ export default {
|
|||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
activeVehicleLookupAlertType: null,
|
||||
needToLookupVehicle: true,
|
||||
vehicleFromLookup: null,
|
||||
vin: this.getVinFromStore(),
|
||||
forwardButtonCarStyle: '',
|
||||
vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0,
|
||||
bailout: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
isCarIdDifferentFromTheStore() {
|
||||
return (
|
||||
|
|
@ -105,18 +125,19 @@ export default {
|
|||
},
|
||||
isTwoIdenticalYMMVehicleFound() {
|
||||
const vinYmmFound = `${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model}`;
|
||||
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return(vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase());
|
||||
const vinYmmExpected
|
||||
= `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
|
||||
return (vinYmmFound.toLowerCase() === vinYmmExpected.toLowerCase());
|
||||
},
|
||||
vinMask() {
|
||||
if (this.vinPopulatedOnPageLoad) {
|
||||
// TODO: Modify to remove side effects in computed
|
||||
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.PERFECT_MATCH;
|
||||
this.needToLookupVehicle = false;
|
||||
const lastSixChars = this.vin.substring(11, this.vin.length);
|
||||
return `!X!X!X!X!X!X!X!X!X!X!X${lastSixChars}`;
|
||||
} else {
|
||||
return 'XXXXXXXXXXXXXXXXX';
|
||||
}
|
||||
return 'XXXXXXXXXXXXXXXXX';
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
|
|
@ -124,9 +145,7 @@ export default {
|
|||
this.resetActiveAlert();
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
this.needToLookupVehicle = true;
|
||||
this.$refs.siteFooter.updateButtonText(
|
||||
this.getCmsContent('SiteFooterWidget', 'ForwardButtonText')
|
||||
);
|
||||
this.$refs.siteFooter.updateButtonText(this.getCmsContent('SiteFooterWidget', 'ForwardButtonText'));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -159,12 +178,11 @@ export default {
|
|||
// because the form itself actually passes its client-side validation.
|
||||
// SSR-189 Scenario #4.
|
||||
this.$refs.siteFooter.enableForwardAction();
|
||||
this.bailout = true
|
||||
this.bailout = true;
|
||||
}
|
||||
|
||||
if (this.bailout) {
|
||||
return this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
|
||||
return this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
|
||||
this.$route);
|
||||
}
|
||||
// Add vin bcs the response from the service doesn't contain vin
|
||||
|
|
@ -179,31 +197,30 @@ export default {
|
|||
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_MATCHED;
|
||||
}
|
||||
|
||||
const vehicleYearMakeModelStyle = `${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model} ${this.forwardButtonCarStyle}`;
|
||||
const vehicleYearMakeModelStyle
|
||||
= `${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model} ${this.forwardButtonCarStyle}`;
|
||||
this.$refs.siteFooter.updateButtonText(`Continue with ${vehicleYearMakeModelStyle}`);
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
|
||||
this.needToLookupVehicle = false;
|
||||
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
let isSelectedGlassAvailableForVehicle = true;
|
||||
if (this.isCarIdDifferentFromTheStore) {
|
||||
isSelectedGlassAvailableForVehicle =
|
||||
await isGlassAvailableForCarId(this.vehicleFromLookup.carId);
|
||||
isSelectedGlassAvailableForVehicle
|
||||
= await isGlassAvailableForCarId(this.vehicleFromLookup.carId);
|
||||
}
|
||||
|
||||
// navigate back to vehicle-damage
|
||||
if (this.isCarIdDifferentFromTheStore && !isSelectedGlassAvailableForVehicle) {
|
||||
this.mainStore.updateVehicle(this.vehicleFromLookup);
|
||||
this.mainStore.resetDamageState();
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$router.navigate(this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
|
||||
this.$route,
|
||||
{},
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
|
||||
);
|
||||
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true });
|
||||
|
||||
// navigate() doesn't stop the processing flow
|
||||
return;
|
||||
|
|
@ -219,7 +236,7 @@ export default {
|
|||
// To Do: Need requirement on what to do here
|
||||
console.error('Error on retrieving PartsOrQuestions');
|
||||
this.$refs.siteFooter.removeLoader();
|
||||
return;
|
||||
return null;
|
||||
}
|
||||
|
||||
// Comes from vehicleQuestionsMixin.navigateForward()
|
||||
|
|
@ -233,20 +250,19 @@ export default {
|
|||
} catch (responseError) {
|
||||
return {
|
||||
error: {
|
||||
status: responseError.status,
|
||||
},
|
||||
status: responseError.status
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
async lookupVehicleByVin(vin) {
|
||||
try {
|
||||
return await this.mainStore.lookupVehicleByVin(vin);
|
||||
}
|
||||
catch (responseError) {
|
||||
} catch (responseError) {
|
||||
return {
|
||||
error: {
|
||||
status: responseError.status,
|
||||
},
|
||||
status: responseError.status
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
|
|
@ -256,7 +272,7 @@ export default {
|
|||
resetVehicleFromLookup() {
|
||||
this.vehicleFromLookup = null;
|
||||
},
|
||||
resetDependentState() {},
|
||||
},
|
||||
resetDependentState() {}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -1,14 +1,13 @@
|
|||
<template>
|
||||
<textboxQuestion
|
||||
id="vin-question-wrapper"
|
||||
v-model="vin"
|
||||
cmsWidgetName="VinNumberQuestionWidget"
|
||||
disableAutoFill
|
||||
id="vin-question-wrapper"
|
||||
inputId="vin-question"
|
||||
isRequired
|
||||
maxLength="17"
|
||||
validationRules="vin-required|vin-format"
|
||||
/>
|
||||
validationRules="vin-required|vin-format" />
|
||||
</template>
|
||||
<script>
|
||||
// Import Other Supporting File(s)
|
||||
|
|
@ -17,20 +16,20 @@ import { regex, required } from '@/helpers/validation-rules';
|
|||
import { errorMessages } from '@/constants/error-messages';
|
||||
|
||||
// Import Component(s)
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question';
|
||||
|
||||
defineRule('vin-required', required(errorMessages.VIN_REQUIRED));
|
||||
defineRule('vin-format', regex(/^[a-hA-Hj-nJ-NpPr-zR-Z0-9]{17}$/, errorMessages.VIN_FORMAT));
|
||||
|
||||
export default {
|
||||
name: 'vin-question',
|
||||
components: {
|
||||
textboxQuestion
|
||||
},
|
||||
props: {
|
||||
modelValue: String
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
components: {
|
||||
textboxQuestion
|
||||
},
|
||||
computed: {
|
||||
vin: {
|
||||
get() {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import welcomePage from '@/layouts/welcome-page/welcome-page.vue';
|
||||
import welcomePage from '@/layouts/welcome-page/welcome-page';
|
||||
|
||||
// Supporting files
|
||||
// Supporting files
|
||||
|
|
@ -110,13 +110,11 @@ describe('navigation', () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
mockvehicles
|
||||
);
|
||||
mockvehicles);
|
||||
});
|
||||
test('if policy is found, but no vehicles, navigate to vehicle-selection page', async () => {
|
||||
// Arrange
|
||||
|
|
@ -138,10 +136,8 @@ describe('navigation', () => {
|
|||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
undefined
|
||||
);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
undefined);
|
||||
});
|
||||
test('if policy is not found, navigate to policy-holder-details page', async () => {
|
||||
// Arrange
|
||||
|
|
@ -158,10 +154,8 @@ describe('navigation', () => {
|
|||
await wrapper.vm.navigateForward();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
undefined
|
||||
);
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
undefined);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
@ -172,31 +166,27 @@ function setupMocks({
|
|||
policies = [],
|
||||
getCoveragePolicyInfoResponse
|
||||
}) {
|
||||
useMainStore().getCoveragePolicyInfo = jest.fn().mockImplementation(() => {
|
||||
return Promise.resolve({
|
||||
data: getCoveragePolicyInfoResponse
|
||||
? getCoveragePolicyInfoResponse
|
||||
: {
|
||||
policies: [
|
||||
useMainStore().getCoveragePolicyInfo = jest.fn().mockImplementation(() => Promise.resolve({
|
||||
data: getCoveragePolicyInfoResponse || {
|
||||
policies: [
|
||||
{
|
||||
insureds: [
|
||||
{
|
||||
insureds: [
|
||||
{
|
||||
customerId: 'TEST_ID'
|
||||
}
|
||||
],
|
||||
vehicles: [
|
||||
{
|
||||
vin: 'TEST_VIN'
|
||||
},
|
||||
{
|
||||
vin: 'TEST_VIN2'
|
||||
}
|
||||
]
|
||||
customerId: 'TEST_ID'
|
||||
}
|
||||
],
|
||||
vehicles: [
|
||||
{
|
||||
vin: 'TEST_VIN'
|
||||
},
|
||||
{
|
||||
vin: 'TEST_VIN2'
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
||||
]
|
||||
}
|
||||
}));
|
||||
|
||||
// Mock api responses
|
||||
const apiResponses = {
|
||||
|
|
@ -213,7 +203,7 @@ function setupMocks({
|
|||
SiteFooterWidget: pageFooterWidgetCmsContent
|
||||
},
|
||||
policyLookupResponse: {
|
||||
policies: policies
|
||||
policies
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,79 +1,88 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
||||
<Form
|
||||
ref="theForm"
|
||||
v-slot="{ meta }"
|
||||
@submit="onSubmit"
|
||||
@invalid-submit="onInvalidSubmit">
|
||||
<div class="page-container-grouped-styles welcome">
|
||||
<div class="fade-on-route-transition position-relative">
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget"/>
|
||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" class="mt-4"/>
|
||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-4" />
|
||||
<div class="container-fluid px-5">
|
||||
<div class="row mt-5">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="policyNumber"
|
||||
v-model="welcomePageModel.policyNumber"
|
||||
inputId="policyNumberField"
|
||||
cmsWidgetName="PolicyNumberQuestion"
|
||||
v-model="welcomePageModel.policyNumber"
|
||||
isRequired
|
||||
ref="policyNumber"
|
||||
disableAutoFill
|
||||
:isDisabled="isPolicyHolderEnabled"
|
||||
:validationRules="rules.policyNumber" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4" v-if="this.isCoverageEnabled">
|
||||
<div
|
||||
v-if="isCoverageEnabled"
|
||||
class="row mt-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="policyZip"
|
||||
v-model="welcomePageModel.policyZipCode"
|
||||
inputId="policyZipCode"
|
||||
cmsWidgetName="PolicyZipQuestion"
|
||||
v-model="welcomePageModel.policyZipCode"
|
||||
isRequired
|
||||
ref="policyZip"
|
||||
:validationRules="rules.policyZip" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="dateOfLoss"
|
||||
v-model="welcomePageModel.dateOfLoss"
|
||||
type="date"
|
||||
cmsWidgetName="DateOfLossQuestion"
|
||||
v-model="welcomePageModel.dateOfLoss"
|
||||
inputId="dateOfLossField"
|
||||
isRequired
|
||||
ref="dateOfLoss"
|
||||
disableAutoFill
|
||||
:max="new Date().toJSON().slice(0,10)"
|
||||
:min="'1972-12-01'"
|
||||
:validationRules="rules.lossDate"
|
||||
/>
|
||||
:validationRules="rules.lossDate" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-4">
|
||||
<div class="col px-0">
|
||||
<textBlock cmsWidgetName="DamageDateEstimateWidget" typeStyle="small" class="mt-2" />
|
||||
<textBlock
|
||||
cmsWidgetName="DamageDateEstimateWidget"
|
||||
typeStyle="small"
|
||||
class="mt-2" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4">
|
||||
<div class="col">
|
||||
<dropdownQuestion
|
||||
cmsWidgetName="DamageCauseQuestion"
|
||||
v-model="welcomePageModel.damageCause"
|
||||
id="welcomeDropdown"
|
||||
ref="damageCause"
|
||||
v-model="welcomePageModel.damageCause"
|
||||
cmsWidgetName="DamageCauseQuestion"
|
||||
inputId="damageCauseQuestionField"
|
||||
:options="DamageCauseOptions"
|
||||
disableAutoFill
|
||||
:validationRules="rules.damageOption"
|
||||
placeHolderText="Select an option"
|
||||
id="welcomeDropdown"
|
||||
/>
|
||||
placeHolderText="Select an option" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mt-4 ">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="phoneNumber"
|
||||
v-model="welcomePageModel.phoneNumber"
|
||||
inputId="phoneNumberField"
|
||||
cmsWidgetName="PhoneNumberQuestion"
|
||||
v-model="welcomePageModel.phoneNumber"
|
||||
:validationRules="rules.phoneNumber"
|
||||
isRequired
|
||||
ref="phoneNumber"
|
||||
mask="###-###-####"
|
||||
disableAutoFill />
|
||||
</div>
|
||||
|
|
@ -81,10 +90,10 @@
|
|||
<div class="row mt-4">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
ref="email"
|
||||
v-model="welcomePageModel.email"
|
||||
inputId="emailField"
|
||||
cmsWidgetName="EmailAddressQuestion"
|
||||
v-model="welcomePageModel.email"
|
||||
ref="email"
|
||||
:validationRules="rules.email"
|
||||
isRequired
|
||||
disableAutoFill />
|
||||
|
|
@ -93,40 +102,41 @@
|
|||
<div class="row">
|
||||
<div class="col">
|
||||
<textboxQuestion
|
||||
v-if="displayDamageCityQuestion"
|
||||
ref="damageCity"
|
||||
v-model="welcomePageModel.damageCity"
|
||||
class="mt-4"
|
||||
inputId="damageCityField"
|
||||
cmsWidgetName="DamageCityQuestion"
|
||||
v-model="welcomePageModel.damageCity"
|
||||
isRequired
|
||||
ref="damageCity"
|
||||
disableAutoFill
|
||||
v-if="this.displayDamageCityQuestion"
|
||||
:validationRules="rules.lossCity" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<dropdownQuestion
|
||||
v-if="displayDamageStateQuestion"
|
||||
id="welcomeDropdown"
|
||||
ref="state"
|
||||
v-model="welcomePageModel.damageState"
|
||||
class="mt-4"
|
||||
cmsWidgetName="DamageStateQuestion"
|
||||
v-model="welcomePageModel.damageState"
|
||||
ref="state"
|
||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||
:options="getStates"
|
||||
:validationRules="rules.lossState"
|
||||
isRequired
|
||||
disableAutoFill
|
||||
v-if="this.displayDamageStateQuestion"
|
||||
placeHolderText="Select an option"
|
||||
id="welcomeDropdown"
|
||||
/>
|
||||
placeHolderText="Select an option" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<buttonQuestion
|
||||
v-if="displayGlassOnlyQuestion"
|
||||
ref="glassOnlyDamage"
|
||||
v-model="welcomePageModel.isDamageGlassOnly"
|
||||
class="px-0 mt-4"
|
||||
cmsWidgetName="GlassOnlyQuestion"
|
||||
v-model="welcomePageModel.isDamageGlassOnly"
|
||||
inputId="isDamageGlassOnly"
|
||||
:answers="DamageGlassOnlyOptions"
|
||||
:questionText="DamageGlassOnlyQuestion"
|
||||
|
|
@ -134,11 +144,11 @@
|
|||
:validationRules="rules.damageOption"
|
||||
isRequired
|
||||
isSmallQuestionLabelText
|
||||
ref="glassOnlyDamage"
|
||||
v-if="this.displayGlassOnlyQuestion"
|
||||
disableAutoFill/>
|
||||
disableAutoFill />
|
||||
</div>
|
||||
<div class="row position-sticky top-100" id="welcomeFooter">
|
||||
<div
|
||||
id="welcomeFooter"
|
||||
class="row position-sticky top-100">
|
||||
<div class="col">
|
||||
<siteFooter
|
||||
class="mt-3"
|
||||
|
|
@ -172,7 +182,7 @@ import { required, regex } from '@/helpers/validation-rules';
|
|||
import { errorMessages } from '@/constants/error-messages';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import { states } from '@/constants/states'
|
||||
import { states } from '@/constants/states';
|
||||
import globalRules from '@/constants/global-rules';
|
||||
|
||||
// define validation rules
|
||||
|
|
@ -186,7 +196,45 @@ defineRule('policy-zip-format', regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages
|
|||
|
||||
export default {
|
||||
name: 'welcome-page',
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
buttonQuestion,
|
||||
textboxQuestion,
|
||||
dropdownQuestion,
|
||||
siteFooter,
|
||||
textBlock,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
}
|
||||
];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
const resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
// Set order account number from the issConfig.
|
||||
mainStore.order.accountNumber = mainStore.issConfig.accountNumber;
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
welcomePageModel: this.getWelcomePageModelFromStore(),
|
||||
|
|
@ -203,32 +251,43 @@ export default {
|
|||
}
|
||||
};
|
||||
},
|
||||
setup() {
|
||||
const mainStore = useMainStore();
|
||||
|
||||
// Set order account number from the issConfig.
|
||||
mainStore.order.accountNumber = mainStore.issConfig.accountNumber;
|
||||
|
||||
return { mainStore };
|
||||
},
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
// Call APIs
|
||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
{
|
||||
resultKey: 'cmsContent',
|
||||
promise: cmsContentPromise
|
||||
computed: {
|
||||
DamageCauseOptions() {
|
||||
const damageCauseAnswers = this.getCmsContent('DamageCauseQuestion', 'Answers');
|
||||
const damageCauseAnswersObj = {};
|
||||
if (damageCauseAnswers) {
|
||||
for (const answer of Object.values(damageCauseAnswers)) {
|
||||
if (answer?.Name) {
|
||||
damageCauseAnswersObj[answer.Name] = answer.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
// use resultMap to populate layout content.
|
||||
let resultMap = await settleAllPromises(promiseResultMap);
|
||||
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
});
|
||||
return damageCauseAnswersObj;
|
||||
},
|
||||
DamageGlassOnlyOptions() {
|
||||
return this.getCmsContent('GlassOnlyQuestion', 'Answers');
|
||||
},
|
||||
DamageGlassOnlyQuestion() {
|
||||
return this.getCmsContent('GlassOnlyQuestion', 'QuestionText');
|
||||
},
|
||||
displayDamageCityQuestion() {
|
||||
return !!this.getCmsContent('DamageCityQuestion', 'QuestionText');
|
||||
},
|
||||
displayDamageStateQuestion() {
|
||||
return !!this.getCmsContent('DamageStateQuestion', 'QuestionText');
|
||||
},
|
||||
displayGlassOnlyQuestion() {
|
||||
return !!this.getCmsContent('GlassOnlyQuestion', 'QuestionText');
|
||||
},
|
||||
getStates() {
|
||||
return states;
|
||||
},
|
||||
isPolicyHolderEnabled() {
|
||||
return !!this.mainStore.issConfig.disabledFields.policyNumber;
|
||||
},
|
||||
isCoverageEnabled() {
|
||||
return this.mainStore.issConfig.isCoverageEnabled;
|
||||
}
|
||||
},
|
||||
methods:
|
||||
{
|
||||
|
|
@ -282,27 +341,21 @@ export default {
|
|||
if (policy) {
|
||||
if (this.vehiclesFound) {
|
||||
// if policy lookup is successful and vehicles are found, navigate to policy-vehicles page
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_WITH_VEHICLES,
|
||||
this.$route,
|
||||
{},
|
||||
{},
|
||||
this.vehiclesFound
|
||||
);
|
||||
this.vehiclesFound);
|
||||
} else {
|
||||
// if policy lookup is successful, but no vehicles are associated with the policy
|
||||
// navigate to vehicle-selection page (manual entry)
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.$route
|
||||
);
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
this.$route);
|
||||
}
|
||||
} else {
|
||||
// if policy lookup is unsuccessful, navigate to policy-holder-details page
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
this.$route
|
||||
);
|
||||
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
this.$route);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
@ -318,58 +371,10 @@ export default {
|
|||
phoneNumber: this.mainStore.order.customer.phoneNumber,
|
||||
email: this.mainStore.order.customer.emailAddress,
|
||||
isPolicyNumberDisabled: this.mainStore.order.policy.isPolicyNumberDisabled
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
DamageCauseOptions() {
|
||||
const damageCauseAnswers = this.getCmsContent('DamageCauseQuestion', 'Answers');
|
||||
const damageCauseAnswersObj = {};
|
||||
if (damageCauseAnswers) {
|
||||
for (let answer of Object.values(damageCauseAnswers)) {
|
||||
if (answer?.Name) {
|
||||
damageCauseAnswersObj[answer.Name] = answer.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return damageCauseAnswersObj;
|
||||
},
|
||||
DamageGlassOnlyOptions() {
|
||||
return this.getCmsContent('GlassOnlyQuestion', 'Answers');
|
||||
},
|
||||
DamageGlassOnlyQuestion() {
|
||||
return this.getCmsContent('GlassOnlyQuestion', 'QuestionText');
|
||||
},
|
||||
displayDamageCityQuestion() {
|
||||
return !!this.getCmsContent('DamageCityQuestion', 'QuestionText');
|
||||
},
|
||||
displayDamageStateQuestion() {
|
||||
return !!this.getCmsContent('DamageStateQuestion', 'QuestionText');
|
||||
},
|
||||
displayGlassOnlyQuestion() {
|
||||
return !!this.getCmsContent('GlassOnlyQuestion', 'QuestionText');
|
||||
},
|
||||
getStates() {
|
||||
return states;
|
||||
},
|
||||
isPolicyHolderEnabled() {
|
||||
return !!this.mainStore.issConfig.disabledFields.policyNumber;
|
||||
},
|
||||
isCoverageEnabled() {
|
||||
return this.mainStore.issConfig.isCoverageEnabled;
|
||||
}
|
||||
},
|
||||
components: {
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
buttonQuestion,
|
||||
textboxQuestion,
|
||||
dropdownQuestion,
|
||||
siteFooter,
|
||||
textBlock,
|
||||
Form,
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { createWebHistory, createRouter } from 'vue-router';
|
||||
import { lazyLoadComponent } from '@/router/dynamic-routing/component-loader';
|
||||
import {issPageValues} from '@/router/router-constants/issPage-values';
|
||||
import { issPageValues } from '@/router/router-constants/issPage-values';
|
||||
import { routingTable } from '@/router/router-constants/routing-table';
|
||||
import { useMainStore } from '@/store';
|
||||
import eventBus from '@/helpers/event-bus/event-bus';
|
||||
|
|
@ -25,7 +25,7 @@ const routes = [
|
|||
to.query.issPage = !to.query.issPage ? issPageValues.WELCOME_PAGE : to.query.issPage;
|
||||
|
||||
// Do not run these for the main entry page - as it is not part of the user flow.
|
||||
if (to.query.issPage != issPageValues.ENTRY_PAG ) {
|
||||
if (to.query.issPage !== issPageValues.ENTRY_PAG) {
|
||||
if (analyticsMixin.methods.noSession()) {
|
||||
await analyticsMixin.methods.initSession();
|
||||
} else {
|
||||
|
|
@ -45,7 +45,7 @@ const routes = [
|
|||
const routeData = await GetRouteInfoFromPageName(to.query.issPage);
|
||||
|
||||
if (routeData[0].name.toLowerCase() === 'error') {
|
||||
throw('Page not found!');
|
||||
throw new Error('Page not found!');
|
||||
}
|
||||
|
||||
// Add our dynamic route.
|
||||
|
|
@ -74,7 +74,7 @@ const router = createRouter({
|
|||
routes,
|
||||
scrollBehavior(to, from, savedPosition) {
|
||||
// always scroll to top
|
||||
return { top: 0 }
|
||||
return { top: 0 };
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -84,7 +84,7 @@ router.afterEach((to, from) => { /*eslint-disable-line*/
|
|||
// Update lastPageVisited in the store
|
||||
store.updateLastPageVisited(to.name);
|
||||
|
||||
if (to.query.issPage != issPageValues.ENTRY_PAGE) {
|
||||
if (to.query.issPage !== issPageValues.ENTRY_PAGE) {
|
||||
// Push page view to GA
|
||||
analyticsMixin.methods.pushPageViewToGA();
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ async function GetRouteInfoFromPageName(pageName) {
|
|||
const response = await useMainStore().getRouteInfo(pageName);
|
||||
|
||||
const jsonFromResponse = JSON.parse(response.data.Result);
|
||||
let routeData = [];
|
||||
const routeData = [];
|
||||
|
||||
// Add our route data and return our array.
|
||||
Object.keys(jsonFromResponse).forEach((key) => {
|
||||
|
|
@ -114,29 +114,25 @@ async function GetRouteInfoFromPageName(pageName) {
|
|||
}
|
||||
|
||||
// Use this navigation when you need to call next() explicitly. beforeRouteEnter is a good example.
|
||||
router.overrideNavigation = (
|
||||
scenario,
|
||||
router.overrideNavigation = (scenario,
|
||||
currentRoute,
|
||||
next,
|
||||
isSavingNavigation,
|
||||
optionalQuery = {},
|
||||
optionalParams = {},
|
||||
optionalPageData
|
||||
) => {
|
||||
navigate(
|
||||
scenario,
|
||||
optionalPageData) => {
|
||||
navigate(scenario,
|
||||
currentRoute,
|
||||
isSavingNavigation,
|
||||
optionalQuery,
|
||||
optionalParams,
|
||||
optionalPageData
|
||||
);
|
||||
optionalPageData);
|
||||
next();
|
||||
};
|
||||
|
||||
router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) => {
|
||||
navigate(scenario, currentRoute, optionalQuery, optionalParams, optionalPageData);
|
||||
}
|
||||
};
|
||||
|
||||
// Navigate to the next route, depending on the scenario.
|
||||
function navigate (scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) { /*eslint-disable-line*/
|
||||
|
|
@ -156,14 +152,13 @@ function navigate (scenario, currentRoute, optionalQuery = {}, optionalParams =
|
|||
if (matchingScenarioMap.destinationIssPageValue) {
|
||||
// Update page data to the store for next page if provided. Otherwise, keep existing page data or set to empty object
|
||||
const existingPageDataForPage = useMainStore().pageData(matchingScenarioMap.destinationIssPageValue);
|
||||
baseMixin.methods.savePageDataToStore(
|
||||
matchingScenarioMap.destinationIssPageValue,
|
||||
baseMixin.methods.savePageDataToStore(matchingScenarioMap.destinationIssPageValue,
|
||||
Object.keys(optionalPageData).length > 0
|
||||
? optionalPageData
|
||||
: existingPageDataForPage ?? {}
|
||||
);
|
||||
: existingPageDataForPage ?? {});
|
||||
|
||||
// We're always pushing the same path, just changing query strings. Make sure our optional query strings get combined with our issPage one.
|
||||
// We're always pushing the same path, just changing query strings.
|
||||
// Make sure our optional query strings get combined with our issPage one.
|
||||
router.push({
|
||||
name: 'root',
|
||||
query: Object.assign(optionalQuery, {
|
||||
|
|
@ -174,7 +169,7 @@ function navigate (scenario, currentRoute, optionalQuery = {}, optionalParams =
|
|||
} else if (matchingScenarioMap.destinationUrl) {
|
||||
navigateToUrl(matchingScenarioMap.destinationUrl, optionalQuery);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Navigate to an external url.
|
||||
function navigateToUrl(url, optionalQuery = {}) {
|
||||
|
|
@ -185,28 +180,25 @@ function navigateToUrl(url, optionalQuery = {}) {
|
|||
}
|
||||
|
||||
window.location.assign(externalUrl);
|
||||
};
|
||||
}
|
||||
|
||||
// Get navigation map depending on the scenario and the current 'page' you're on.
|
||||
function getNavigationMap (scenario, currentRoute) {
|
||||
function getNavigationMap(scenario, currentRoute) {
|
||||
const issPageValue = currentRoute.query.issPage;
|
||||
try {
|
||||
const matchedQueryValue = routingTable(useMainStore())
|
||||
.filter(
|
||||
(item) =>
|
||||
item.issPageValue === issPageValue &&
|
||||
item.maps.filter((map) => map.scenario === scenario).length > 0
|
||||
);
|
||||
.filter((item) =>
|
||||
item.issPageValue === issPageValue
|
||||
&& item.maps.filter((map) => map.scenario === scenario).length > 0);
|
||||
|
||||
let maps = matchedQueryValue ? matchedQueryValue.map((m) => m.maps.filter((map) => map.scenario === scenario))[0] : undefined;
|
||||
const maps = matchedQueryValue ? matchedQueryValue.map((m) => m.maps.filter((map) => map.scenario === scenario))[0] : undefined;
|
||||
|
||||
return maps ? maps.filter(x => x.filter === true || x.filter === undefined)[0] : undefined;
|
||||
}
|
||||
catch (e) {
|
||||
return maps ? maps.filter((x) => x.filter === true || x.filter === undefined)[0] : undefined;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function GoToStartOn404(next) {
|
||||
const errorPageName = issPageValues.WELCOME_PAGE;
|
||||
|
|
@ -217,22 +209,20 @@ function GoToStartOn404(next) {
|
|||
});
|
||||
|
||||
// Put item on the bus
|
||||
eventBus.addEventToBus(
|
||||
globalEvents.Categories.GLOBAL_ALERT,
|
||||
eventBus.addEventToBus(globalEvents.Categories.GLOBAL_ALERT,
|
||||
globalEvents.SubCategories.PAGE_NOT_FOUND,
|
||||
{
|
||||
isDismissible: true,
|
||||
messageCopy: 'You can get a quote by starting on this page.',
|
||||
messageHeadline: "We're sorry, something went wrong.",
|
||||
type: globalEventTypes.Danger
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
next({
|
||||
name: errorPageName,
|
||||
query: {issPage: errorPageName }
|
||||
query: { issPage: errorPageName }
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Run SiteEntry and PageEntry triggers for experiments
|
||||
async function runExperiments(nextPage) {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ export const issPageValues = {
|
|||
REVIEW_PAGE: 'review-page',
|
||||
REVEAL: 'reveal',
|
||||
SERVICE_LOCATION: 'service-location',
|
||||
TPA_CONFIRMATION:'tpa-confirmation',
|
||||
TPA_CONFIRMATION: 'tpa-confirmation',
|
||||
SERVICE_PACKAGES: 'service-packages',
|
||||
SCHEDULE_PAGE: 'schedule-page',
|
||||
VEHICLE_DAMAGE: 'vehicle-damage',
|
||||
|
|
@ -28,7 +28,6 @@ export const issPageValues = {
|
|||
VEHICLE_SELECTION: 'vehicle-selection',
|
||||
VIN_LOOKUP: 'vin-lookup',
|
||||
TPA_SUBMIT: 'tpa-submit',
|
||||
BAILOUT_PAGE: 'bailout-page',
|
||||
TPA_SEARCH: 'tpa-search',
|
||||
POLICY_VEHICLES:'policy-vehicles'
|
||||
POLICY_VEHICLES: 'policy-vehicles'
|
||||
};
|
||||
|
|
|
|||
|
|
@ -18,7 +18,6 @@ const navigationScenarios = {
|
|||
SELECTED_STYLE: 'SELECTED_STYLE',
|
||||
|
||||
// Policy Holder Details
|
||||
CLICKED_FORWARD_POLICY_UNVERIFIED: 'CLICKED_FORWARD_POLICY_UNVERIFIED',
|
||||
CLICKED_FORWARD_POLICY_VERIFIED: 'CLICKED_FORWARD_POLICY_VERIFIED',
|
||||
|
||||
// Policy Vehicle
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -13,12 +13,12 @@ describe('Router', () => {
|
|||
});
|
||||
|
||||
it('Should push next view when navigating locally', () => {
|
||||
let scenario = navigationScenarios.CLICKED_FORWARD;
|
||||
let currentRoute = { query: { issPage: issPageValues.WELCOME_PAGE }};
|
||||
const scenario = navigationScenarios.CLICKED_FORWARD;
|
||||
const currentRoute = { query: { issPage: issPageValues.WELCOME_PAGE } };
|
||||
|
||||
router.push = jest.fn();
|
||||
|
||||
router.navigate(scenario, currentRoute);
|
||||
expect(router.push.mock.calls[0][0].query.issPage).toBe(issPageValues.POLICY_HOLDER_DETAILS);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue