Merge pull request #233 from Safelite/SSR-348-site-header-unstick-2

Ssr 348 site header unstick 2
This commit is contained in:
bmauger 2023-04-10 15:08:27 -04:00 committed by GitHub
commit 785a75fa62
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 2250 additions and 2097 deletions

View file

@ -2,22 +2,6 @@ import { shallowMount } from "@vue/test-utils";
import buttonQuestion from "@/digital-components/button-question/button-question"; import buttonQuestion from "@/digital-components/button-question/button-question";
import { getMountOptions } from "@/helpers/unit-test-helper.js"; import { getMountOptions } from "@/helpers/unit-test-helper.js";
describe("buttonQuestion.vue", () => {
it("Should show overflow classes on fieldset if isOverflowScrollable is true", () => {
// Act
const wrapper = shallowMount(buttonQuestion, {
propsData: {
isOverflowScrollable: true,
groupName: "group-name",
},
});
// Assert
const fieldSet = wrapper.find("fieldset");
expect(fieldSet.classes()).toContain("overflow-scroll");
});
});
describe("buttonQuestion.vue", () => { describe("buttonQuestion.vue", () => {
it("Fieldset classes should contain row if button type is listCard", () => { it("Fieldset classes should contain row if button type is listCard", () => {
// Act // Act

View file

@ -4,7 +4,7 @@
:class=" :class="
isOverflowScrollable ? 'button-question button-question-overflow' : 'button-question' isOverflowScrollable ? 'button-question button-question-overflow' : 'button-question'
"> ">
<div v-if="questionText && answers && answers.length > 0" class="question-text d-flex" <div v-if="questionText && answers && answers.length > 0" class="question-text d-flex"
:class="{'small-question-text': isSmallQuestionText,'small-question-label-text':isSmallQuestionLabelText}"> :class="{'small-question-text': isSmallQuestionText,'small-question-label-text':isSmallQuestionLabelText}">
<span class="fw-bold w-100">{{ questionText }}</span> <span class="fw-bold w-100">{{ questionText }}</span>
</div> </div>
@ -13,7 +13,6 @@
<fieldset <fieldset
class="w-100" class="w-100"
:aria-required="isRequired" :aria-required="isRequired"
:class="getFieldSetClasses"
:role="isMultiSelect ? 'group' : 'radiogroup'" :role="isMultiSelect ? 'group' : 'radiogroup'"
:aria-labelledby="formatString(groupName)"> :aria-labelledby="formatString(groupName)">
<legend <legend
@ -145,7 +144,7 @@ export default {
const SmallQuestionTextClass = this.isSmallQuestionText const SmallQuestionTextClass = this.isSmallQuestionText
? baseClasses + "small-question-text" ? baseClasses + "small-question-text"
: baseClasses; : baseClasses;
const SmallQuestionLabelText = this.isSmallQuestionLabelText const SmallQuestionLabelText = this.isSmallQuestionLabelText
? SmallQuestionTextClass + "small-question-label-text" ? SmallQuestionTextClass + "small-question-label-text"
@ -234,16 +233,16 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
.button-question-overflow { // .button-question-overflow {
height: calc(100vh - 274px); // height: calc(100vh - 274px);
//
.overflow-scroll { // .overflow-scroll {
// Height will be determined by overall height of content above list // // Height will be determined by overall height of content above list
height: calc(100% - 400px); // height: calc(100% - 400px);
overflow-x: hidden !important; // overflow-x: hidden !important;
-webkit-overflow-scrolling: touch; // -webkit-overflow-scrolling: touch;
} // }
} // }
.button-question { .button-question {
color: $black; color: $black;

View file

@ -1,34 +1,43 @@
<template> <template>
<div :class="`page-container-grouped-styles questions-page`"> <div :class="`page-container-grouped-styles questions-page`">
<loadingModal ref="loadingModal" /> <div class="fade-on-route-transition position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <loadingModal ref="loadingModal" />
<div class="fade-on-route-transition sub-container overflow-scroll px-5"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<vehicleBanner class="mb-3" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" /> <div class="select-car">
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" /> <div class="container-fluid pb-2">
<alert <div class="row px-3">
ref="alertFewMoreQuestions" <div class="col">
cmsWidgetName="alertWidget" <div class="select-car-form rounded">
class="mt-5" <vehicleBanner class="mb-3" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
alertClass="alert-warning" <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
:manualHeadline="alertFewMoreQuestionsHeader" <alert
:manualCopy="alertFewMoreQuestionsCopy" ref="alertFewMoreQuestions"
v-bind:isDismissible="false" /> cmsWidgetName="alertWidget"
<div v-for="(questionsDatum, i) in questionsData" :key="questionsDatum.key"> alertClass="alert-warning"
<questionChain :manualHeadline="alertFewMoreQuestionsHeader"
ref="questionChain" :manualCopy="alertFewMoreQuestionsCopy"
v-model="selectedAnswers[questionsDatum.answerKey]" v-bind:isDismissible="false" />
:questionData="questionsDatum.questions" <div v-for="(questionsDatum, i) in questionsData" :key="questionsDatum.key">
:index="i" <questionChain
v-if="showThisQuestionChain(questionsDatum, i)" ref="questionChain"
:answerKey="questionsDatum.answerKey" v-model="selectedAnswers[questionsDatum.answerKey]"
:validationRules="validationRules" /> :questionData="questionsDatum.questions"
:index="i"
v-if="showThisQuestionChain(questionsDatum, i)"
:answerKey="questionsDatum.answerKey"
:validationRules="validationRules" />
</div>
<siteFooter
ref="siteFooter"
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!isMetaValid"
@back-clicked="handleBackButtonAction"
@ForwardClicked="handleForwardButtonAction" />
</div>
</div>
</div>
</div>
</div> </div>
<siteFooter
ref="siteFooter"
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!isMetaValid"
@back-clicked="handleBackButtonAction"
@ForwardClicked="handleForwardButtonAction" />
</div> </div>
</div> </div>
</template> </template>
@ -94,11 +103,19 @@ export default {
}; };
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.overflow-scroll { .fade-on-route-transition {
height: calc(100% - 180px); margin-bottom: 100px;
overflow-x: hidden !important; }
} .page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
}
.questions-page { .questions-page {
.question-text { .question-text {
margin-bottom: 0.5rem; margin-bottom: 0.5rem;

View file

@ -7,7 +7,7 @@
</button> </button>
</div> </div>
<!-- Modal --> <!-- Modal -->
<div class="modal menu-modal fade" data-bs-backdrop="false" id="footerModal" tabindex="-1" aria-labelledby="footerModalLabel" aria-hidden="true" v-on="{ 'show.bs.modal' : show, 'hide.bs.modal' : hide }" :style="`height: calc(100% - ${currentFooterAndHeaderHeight}px);`"> <div class="modal menu-modal fade" data-bs-backdrop="false" id="footerModal" tabindex="-1" aria-labelledby="footerModalLabel" aria-hidden="true" v-on="{ 'show.bs.modal' : show, 'hide.bs.modal' : hide }">
<div class="menu-modal-container"> <div class="menu-modal-container">
<button <button
class="menu-button" class="menu-button"
@ -79,7 +79,7 @@ export default {
this.currentFooterAndHeaderHeight = this.getFooterInfoBoxHeight() + 72; this.currentFooterAndHeaderHeight = this.getFooterInfoBoxHeight() + 72;
this.isActive = true; this.isActive = true;
document.querySelector('.page-container-grouped-styles').scrollTo({ document.querySelector('.page-container-grouped-styles').scrollTo({
top: 0, behavior: 'smooth' top: 0, behavior: 'instant'
}); });
}, },
hide() { hide() {

View file

@ -1,60 +1,65 @@
<template> <template>
<Form <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
@submit="onSubmit"
@invalid-submit="onInvalidSubmit"
ref="theForm"
v-slot="{ meta }"
autocomplete="off">
<div class="page-container-grouped-styles"> <div class="page-container-grouped-styles">
<siteHeader cmsWidgetName="SiteHeaderWidget" ref="siteHeader" /> <div class="fade-on-route-transition position-relative">
<div class="fade-on-route-transition sub-container overflow-scroll px-5"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<vehicleBanner <div class="select-car">
class="mb-3" <div class="container-fluid pb-2">
cmsWidgetName="VehicleBannerWidget" <div class="row px-3">
ref="vehicleBanner" <div class="col">
:displayGenericVehicleImage="false" /> <div class="select-car-form rounded">
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" ref="siteSubHeader" /> <vehicleBanner
<alert class="mb-3"
ref="alertVinNotFound" cmsWidgetName="VehicleBannerWidget"
v-if="displayVinNotFoundAlert" ref="vehicleBanner"
class="mb-4 mt-4" :displayGenericVehicleImage="false" />
cmsWidgetName="AlertVinNotFoundWidget" <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" ref="siteSubHeader" />
alertClass="alert-danger" <alert
v-bind:isDismissible="false" /> ref="alertVinNotFound"
<alert v-if="displayVinNotFoundAlert"
ref="alertMatchedDifferentVehicle" class="mb-4 mt-4"
v-if="displayMatchedDifferentVehicleAlert" cmsWidgetName="AlertVinNotFoundWidget"
class="mb-4 mt-4" alertClass="alert-danger"
:manualHeadline="AlertMatchedDifferentVehicleHeader" v-bind:isDismissible="false" />
:manualCopy="AlertMatchedDifferentVehicleBody" <alert
alertClass="alert-warning" ref="alertMatchedDifferentVehicle"
v-bind:isDismissible="false" /> v-if="displayMatchedDifferentVehicleAlert"
<alert class="mb-4 mt-4"
ref="alertMatchedTwoIdenticalYMMVehicle" :manualHeadline="AlertMatchedDifferentVehicleHeader"
v-if="displayMatchedTwoIdenticalYMMVehicleAlert" :manualCopy="AlertMatchedDifferentVehicleBody"
class="mb-4 mt-4" alertClass="alert-warning"
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget" v-bind:isDismissible="false" />
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader" <alert
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody" ref="alertMatchedTwoIdenticalYMMVehicle"
alertClass="alert-warning" v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
v-bind:isDismissible="false" /> class="mb-4 mt-4"
<alert cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
ref="alertVinLookupsByHomeAddressNotAllowed" :manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
v-if="displayVinLookupByHomeAddressNotAllowedAlert" :manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
class="mb-4 mt-4" alertClass="alert-warning"
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget" v-bind:isDismissible="false" />
alertClass="alert-danger" <alert
v-bind:isDismissible="false" /> ref="alertVinLookupsByHomeAddressNotAllowed"
v-if="displayVinLookupByHomeAddressNotAllowedAlert"
class="mb-4 mt-4"
cmsWidgetName="AlertVinLookupsByHomeAddressNotAllowedWidget"
alertClass="alert-danger"
v-bind:isDismissible="false" />
<customerQuestions ref="customerQuestions" v-model="customerQuestions" /> <customerQuestions ref="customerQuestions" v-model="customerQuestions" />
<siteFooter <siteFooter
cmsWidgetName="SiteFooterWidget" cmsWidgetName="SiteFooterWidget"
ref="siteFooter" ref="siteFooter"
:isDisabled="!meta.valid" :isDisabled="!meta.valid"
@ForwardClicked="forwardButtonAction" @ForwardClicked="forwardButtonAction"
@back-clicked="backButtonAction" @back-clicked="backButtonAction"
:isForwardActionDisabled="!meta.valid" /> :isForwardActionDisabled="!meta.valid" />
</div>
</div>
</div>
</div>
</div>
</div> </div>
</div> </div>
</Form> </Form>
@ -147,211 +152,217 @@ export default {
let vehicleInfoToCommit = {}; let vehicleInfoToCommit = {};
const vinLookupResponse = useMainStore().lookupVinByAddress ({ const vinLookupResponse = useMainStore().lookupVinByAddress ({
licenseLastName: this.customerQuestions.lastName, licenseLastName: this.customerQuestions.lastName,
licenseStreetAddress: this.customerQuestions.addressQuestions.streetAddress, licenseStreetAddress: this.customerQuestions.addressQuestions.streetAddress,
licenseZip: this.customerQuestions.addressQuestions.zipCode, licenseZip: this.customerQuestions.addressQuestions.zipCode,
licenseState: this.customerQuestions.addressQuestions.state, licenseState: this.customerQuestions.addressQuestions.state,
}
);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "vinLookupResponse",
promise: vinLookupResponse,
}
];
const resultMap = await settleAllPromises(promiseResultMap);
// If VIN Lookup by address is forbidden by State Restrictions then show an alert
if (!resultMap.vinLookupResponse.isStatePermissible) {
// State Restrictions forbid lookup by address
this.displayVinLookupByHomeAddressNotAllowedAlert = true;
this.$refs.siteFooter.disableForwardButton();
return this.$refs.siteFooter.removeLoader();
} }
);
const carsFound = resultMap.vinLookupResponse.vinVehicles; // Settle promises and get results
const promiseResultMap = [
// Handle cases for different amounts of VINS found for the address. {
if (carsFound.length == 1) { resultKey: "vinLookupResponse",
// Single VIN found promise: vinLookupResponse,
const carFound = carsFound[0].vehicle;
this.isCarIdDifferent = carFound.carId !== useMainStore().order.vehicle.carId;
if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) {
// Display Alert
this.previouslyEnteredCarId = carFound.carId;
this.customAlertData.vehicleInfo = carFound;
if(this.isTwoIdenticalYMMVehicleFound){
this.displayMatchedTwoIdenticalYMMVehicleAlert = true;
this.forwardButtonCarStyle= carFound.style;
}
else{
this.displayMatchedDifferentVehicleAlert = true;
}
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
carFound.carId
);
// Update button "Continue with..."
this.$refs.siteFooter.updateButtonText(
`Continue with ${carFound.year} ${carFound.make} ${carFound.model} ${this.forwardButtonCarStyle}`
);
return this.$refs.siteFooter.removeLoader();
}
// update data
vehicleInfoToCommit = Object.assign(carFound, { vin: carsFound[0].vin });
} else if (carsFound.length > 1) {
// If multiple cars were found and one and only one of them matches the carId entered, save the vehicle info
const matchingCars = carsFound.filter(
(vin) => vin.vehicle.carId === this.mainStore.order.vehicle.carId
);
if (matchingCars.length === 1) {
vehicleInfoToCommit = Object.assign(matchingCars[0].vehicle, {
vin: matchingCars[0].vin,
});
}
} else {
// No VINS found.
this.displayVinNotFoundAlert = true;
this.$refs.siteFooter.disableForwardButton();
return this.$refs.siteFooter.removeLoader();
} }
];
// Save vehicle, customer, service and registration information const resultMap = await settleAllPromises(promiseResultMap);
await useMainStore().saveRegistrationAddressLookup( // If VIN Lookup by address is forbidden by State Restrictions then show an alert
{ if (!resultMap.vinLookupResponse.isStatePermissible) {
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle, // State Restrictions forbid lookup by address
vehicleInfo: this.displayVinLookupByHomeAddressNotAllowedAlert = true;
Object.keys(vehicleInfoToCommit).length === 0 this.$refs.siteFooter.disableForwardButton();
? useMainStore().order.vehicle return this.$refs.siteFooter.removeLoader();
: vehicleInfoToCommit,
registrationInfo: {
firstName: this.customerQuestions.firstName,
lastName: this.customerQuestions.lastName,
address: this.customerQuestions.addressQuestions.streetAddress,
city: this.customerQuestions.addressQuestions.city,
state: this.customerQuestions.addressQuestions.state,
zipCode: this.customerQuestions.addressQuestions.zipCode,
},
},
false
);
return await this.navigateForward(carsFound);
},
async navigateForward(carsFound) {
// Match vehicles found to vehicles in state.
const matchingCars = carsFound.filter(
(car) => car.vehicle.carId === useMainStore().order.vehicle.carId
);
// If a different vehicle is found than the one entered and the selected glass is not available for that vehicle then navigate back to "vehicle-damage"
// display vehicle changed alert on that page.
if (
this.isCarIdDifferent &&
!this.isSelectedGlassAvailableForVehicle
) {
this.$router.navigate(
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
} else if (matchingCars.length === 1) {
await this.navigateForwardWithSingleCarMatch();
} else {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
this.$route,
{},
{},
carsFound
);
}
},
resetWarningsAndErrors() {
this.displayVinNotFoundAlert = false;
this.displayMatchedDifferentVehicleAlert = false;
this.displayVinLookupByHomeAddressNotAllowedAlert = false;
this.$refs.siteFooter.enableForwardAction();
},
},
mounted() {
this.attachCustomEvents();
},
computed: {
AlertMatchedDifferentVehicleHeader() {
return this.getCmsContent(
"AlertMatchedDifferentVehicleWidget",
"HeadlineText"
).replaceAll("{custom:damage}", getDamageString());
},
AlertMatchedDifferentVehicleBody() {
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
.replaceAll("{custom:damage}", getDamageString())
.replaceAll("{custom:vinYmmFound}", vinYmmFound)
.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
},
AlertMatchedTwoIdenticalYMMVehicleHeader() {
return this.getCmsContent(
"AlertMatchedTwoIdenticalYMMVehicleWidget",
"HeadlineText"
).replaceAll("{custom:damage}", getDamageString());
},
AlertMatchedTwoIdenticalYMMVehicleBody() {
const vinYmmsFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`;
const vinYmmsExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`;
return this.getCmsContent("AlertMatchedTwoIdenticalYMMVehicleWidget", "BodyText")
.replaceAll("{custom:damage}", getDamageString())
.replaceAll("{custom:vinYmmsFound}", vinYmmsFound)
.replaceAll("{custom:vinYmmsExpected}", vinYmmsExpected);
},
isTwoIdenticalYMMVehicleFound(){
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
return(vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase());
} }
},
watch: { const carsFound = resultMap.vinLookupResponse.vinVehicles;
customerQuestions: {
handler(newValue) { // Handle cases for different amounts of VINS found for the address.
// if they modify one of the lookup fields (address, city, state, zipCode, or lastName), then modify the button text back to "Get my personalized quote" if (carsFound.length == 1) {
// Single VIN found
const carFound = carsFound[0].vehicle;
this.isCarIdDifferent = carFound.carId !== useMainStore().order.vehicle.carId;
if (this.isCarIdDifferent && carFound.carId !== this.previouslyEnteredCarId) {
// Display Alert
this.previouslyEnteredCarId = carFound.carId;
this.customAlertData.vehicleInfo = carFound;
if(this.isTwoIdenticalYMMVehicleFound){
this.displayMatchedTwoIdenticalYMMVehicleAlert = true;
this.forwardButtonCarStyle= carFound.style;
}
else{
this.displayMatchedDifferentVehicleAlert = true;
}
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
carFound.carId
);
// Update button "Continue with..."
this.$refs.siteFooter.updateButtonText( this.$refs.siteFooter.updateButtonText(
this.getCmsContent("siteFooterWidget", "ForwardButtonText") `Continue with ${carFound.year} ${carFound.make} ${carFound.model} ${this.forwardButtonCarStyle}`
); );
this.resetWarningsAndErrors(); return this.$refs.siteFooter.removeLoader();
}
// update data
vehicleInfoToCommit = Object.assign(carFound, { vin: carsFound[0].vin });
} else if (carsFound.length > 1) {
// If multiple cars were found and one and only one of them matches the carId entered, save the vehicle info
const matchingCars = carsFound.filter(
(vin) => vin.vehicle.carId === this.mainStore.order.vehicle.carId
);
if (matchingCars.length === 1) {
vehicleInfoToCommit = Object.assign(matchingCars[0].vehicle, {
vin: matchingCars[0].vin,
});
}
} else {
// No VINS found.
this.displayVinNotFoundAlert = true;
this.$refs.siteFooter.disableForwardButton();
return this.$refs.siteFooter.removeLoader();
}
// Save vehicle, customer, service and registration information
await useMainStore().saveRegistrationAddressLookup(
{
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
vehicleInfo:
Object.keys(vehicleInfoToCommit).length === 0
? useMainStore().order.vehicle
: vehicleInfoToCommit,
registrationInfo: {
firstName: this.customerQuestions.firstName,
lastName: this.customerQuestions.lastName,
address: this.customerQuestions.addressQuestions.streetAddress,
city: this.customerQuestions.addressQuestions.city,
state: this.customerQuestions.addressQuestions.state,
zipCode: this.customerQuestions.addressQuestions.zipCode,
},
}, },
deep: true, false
);
return await this.navigateForward(carsFound);
},
async navigateForward(carsFound) {
// Match vehicles found to vehicles in state.
const matchingCars = carsFound.filter(
(car) => car.vehicle.carId === useMainStore().order.vehicle.carId
);
// If a different vehicle is found than the one entered and the selected glass is not available for that vehicle then navigate back to "vehicle-damage"
// display vehicle changed alert on that page.
if (
this.isCarIdDifferent &&
!this.isSelectedGlassAvailableForVehicle
) {
this.$router.navigate(
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
} else if (matchingCars.length === 1) {
await this.navigateForwardWithSingleCarMatch();
} else {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_MULTIPLE_VEHICLES,
this.$route,
{},
{},
carsFound
);
} }
}, },
components: { resetWarningsAndErrors() {
siteHeader, this.displayVinNotFoundAlert = false;
siteFooter, this.displayMatchedDifferentVehicleAlert = false;
vehicleBanner, this.displayVinLookupByHomeAddressNotAllowedAlert = false;
siteSubHeader, this.$refs.siteFooter.enableForwardAction();
customerQuestions,
textboxQuestion,
alert,
Form,
}, },
},
mounted() {
this.attachCustomEvents();
},
computed: {
AlertMatchedDifferentVehicleHeader() {
return this.getCmsContent(
"AlertMatchedDifferentVehicleWidget",
"HeadlineText"
).replaceAll("{custom:damage}", getDamageString());
},
AlertMatchedDifferentVehicleBody() {
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
.replaceAll("{custom:damage}", getDamageString())
.replaceAll("{custom:vinYmmFound}", vinYmmFound)
.replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
},
AlertMatchedTwoIdenticalYMMVehicleHeader() {
return this.getCmsContent(
"AlertMatchedTwoIdenticalYMMVehicleWidget",
"HeadlineText"
).replaceAll("{custom:damage}", getDamageString());
},
AlertMatchedTwoIdenticalYMMVehicleBody() {
const vinYmmsFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`;
const vinYmmsExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`;
return this.getCmsContent("AlertMatchedTwoIdenticalYMMVehicleWidget", "BodyText")
.replaceAll("{custom:damage}", getDamageString())
.replaceAll("{custom:vinYmmsFound}", vinYmmsFound)
.replaceAll("{custom:vinYmmsExpected}", vinYmmsExpected);
},
isTwoIdenticalYMMVehicleFound(){
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
return(vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase());
}
},
watch: {
customerQuestions: {
handler(newValue) {
// if they modify one of the lookup fields (address, city, state, zipCode, or lastName), then modify the button text back to "Get my personalized quote"
this.$refs.siteFooter.updateButtonText(
this.getCmsContent("siteFooterWidget", "ForwardButtonText")
);
this.resetWarningsAndErrors();
},
deep: true,
}
},
components: {
siteHeader,
siteFooter,
vehicleBanner,
siteSubHeader,
customerQuestions,
textboxQuestion,
alert,
Form,
},
}; };
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.fade-on-route-transition {
.overflow-scroll { margin-bottom: 100px;
height: calc(100% - 180px); }
overflow-X: hidden !important; .page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
} }
</style> </style>

View file

@ -1,50 +1,48 @@
<template> <template>
<Form <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
@submit="onSubmit" <div class="page-container-grouped-styles">
@invalidSubmit="onInvalidSubmit" <div class="fade-on-route-transition position-relative">
v-slot="{ meta }" <siteHeader cmsWidgetName="SiteHeaderWidget" />
> <div class="select-car">
<div class="page-container-grouped-styles"> <div class="container-fluid pb-2">
<siteHeader <div class="row px-3">
cmsWidgetName="SiteHeaderWidget" <div class="col">
/> <div class="select-car-form rounded">
<div class="fade-on-route-transition sub-container overflow-scroll px-5"> <textBlock
<textBlock cmsWidgetName="verifyingCoverageStatement"
cmsWidgetName="verifyingCoverageStatement" typeStyle="h5"
typeStyle="h5" justifyText="center"
justifyText="center" class="mt-0 mb-4"
class="mt-0 mb-4" id="coverage-statement-text-block"
id="coverage-statement-text-block" />
/> <div>
<div> <p v-html="continueWithSchedulingBodyText" class="mt-0 small" ></p>
<p </div>
v-html="continueWithSchedulingBodyText" <textBlock
class="mt-0 small" > cmsWidgetName="whatHappensNextCopy"
</p> class="mt-4 mb-2 fw-bold"
id="coverage-statement-text-block"
/>
<div>
<p class="small" v-html="bodyText" ref="coverageStatementBodyText"></p>
</div>
<recalModal cmsWidgetName="RecalModal" />
<steeringText cmsWidgetName="MASteeringText" ></steeringText>
<siteFooter
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!meta.valid"
@backClicked="navigateBack"
@forwardClicked="forwardButtonAction"
ref="siteFooter"
/>
</div>
</div>
</div>
</div>
</div>
</div>
</div> </div>
<textBlock </Form>
cmsWidgetName="whatHappensNextCopy"
class="mt-4 mb-2 fw-bold"
id="coverage-statement-text-block"
/>
<div>
<p class="small"
v-html="bodyText"
ref="coverageStatementBodyText">
</p>
</div>
<recalModal cmsWidgetName="RecalModal" />
<steeringText cmsWidgetName="MASteeringText" ></steeringText>
<siteFooter
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!meta.valid"
@backClicked="navigateBack"
@forwardClicked="forwardButtonAction"
ref="siteFooter"
/>
</div>
</div>
</Form>
</template> </template>
<script> <script>
@ -65,107 +63,115 @@ import { useMainStore } from "@/store";
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin"; import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
export default { export default {
name: 'coverage-statement', name: 'coverage-statement',
mixins: [baseFormMixin, vehicleQuestionsMixin], mixins: [baseFormMixin, vehicleQuestionsMixin],
components: { components: {
siteFooter, siteFooter,
siteHeader, siteHeader,
siteSubHeader, siteSubHeader,
Form, Form,
textBlock, textBlock,
recalModal, recalModal,
steeringText steeringText
}, },
computed: { computed: {
bodyText() { bodyText() {
if (useMainStore().order.damage.isRepair) { if (useMainStore().order.damage.isRepair) {
return this.unverifiedNonADASRepairBodyText; return this.unverifiedNonADASRepairBodyText;
} }
else { else {
let parts = useMainStore().order.lineItems.glassParts; let parts = useMainStore().order.lineItems.glassParts;
// if ADAS, display ADASNextSteps // if ADAS, display ADASNextSteps
if (parts.filter(part => part.requiresRecalibration).length > 0) { if (parts.filter(part => part.requiresRecalibration).length > 0) {
return this.unverifiedADASNextStepsBodyText; return this.unverifiedADASNextStepsBodyText;
} }
// if non-ADAS, display NonADASNextSteps // if non-ADAS, display NonADASNextSteps
else { else {
return this.unverifiedNonADASNextStepsBodyText; return this.unverifiedNonADASNextStepsBodyText;
} }
} }
},
continueWithSchedulingBodyText() {
return this.getCmsContent("continueWithSchedulingCopy", "BodyText");
},
unverifiedADASNextStepsBodyText() {
return this.getCmsContent("UnverifiedADASNextStepsWidget", "BodyText").replaceAll("{custom:damage}", this.damageText);
},
unverifiedNonADASNextStepsBodyText() {
return this.getCmsContent("UnverifiedNonADASNextStepsWidget", "BodyText").replaceAll("{custom:damage}", this.damageText);
},
unverifiedNonADASRepairBodyText() {
return this.getCmsContent("UnverifiedNonADASRepairWidget", "BodyText");
},
damageText() {
var damageString = getDamageString();
return damageString == "match" ? "" : damageString;
},
}, },
continueWithSchedulingBodyText() { async beforeRouteEnter(to, from, next) {
return this.getCmsContent("continueWithSchedulingCopy", "BodyText"); // Call APIs
}, const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
unverifiedADASNextStepsBodyText() {
return this.getCmsContent("UnverifiedADASNextStepsWidget", "BodyText").replaceAll("{custom:damage}", this.damageText);
},
unverifiedNonADASNextStepsBodyText() {
return this.getCmsContent("UnverifiedNonADASNextStepsWidget", "BodyText").replaceAll("{custom:damage}", this.damageText);
},
unverifiedNonADASRepairBodyText() {
return this.getCmsContent("UnverifiedNonADASRepairWidget", "BodyText");
},
damageText() {
var damageString = getDamageString();
return damageString == "match" ? "" : damageString;
},
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{ {
resultKey: 'cmsContent', resultKey: 'cmsContent',
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
}); });
},
methods: {
arePagePrerequisitesValid() {
if (useMainStore().order.vehicle.vin) {
return true;
}
return false;
}, },
methods: {
arePagePrerequisitesValid() {
if (useMainStore().order.vehicle.vin) {
return true;
}
return false;
},
async forwardButtonAction() { async forwardButtonAction() {
return this.navigateForward(); return this.navigateForward();
}, },
navigateForward() { navigateForward() {
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_COVERAGE_STATEMENT, this.navigationScenarios.CLICKED_FORWARD_COVERAGE_STATEMENT,
this.$route this.$route
); );
},
}, },
},
}; };
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.overflow-scroll { .fade-on-route-transition {
height: calc(100% - 168px); margin-bottom: 100px;
overflow-X: hidden !important; }
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
} }
ol { ol {
margin-left: -1rem; margin-left: -1rem;
li { li {
margin-bottom: .5rem; margin-bottom: .5rem;
line-height: 1.5rem; line-height: 1.5rem;
a { a {
line-height: 1.5rem; line-height: 1.5rem;
padding: 0; padding: 0;
} }
} }
} }
#coverage-statement-text-block { #coverage-statement-text-block {
color: #000000; color: #000000;

View file

@ -1,67 +1,71 @@
<template> <template>
<Form <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
@submit="onSubmit" <div class="page-container-grouped-styles">
@invalid-submit="onInvalidSubmit" <div class="fade-on-route-transition position-relative">
v-slot="{ meta }"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="page-container-grouped-styles"> <div class="select-car">
<siteHeader cms-widget-name="SiteHeaderWidget" /> <div class="container-fluid pb-2">
<div class="fade-on-route-transition sub-container overflow-scroll mt-5 px-5"> <div class="row px-3">
<vehicleBanner <div class="col">
class="mb-3" <div class="select-car-form rounded">
cms-widget-name="VehicleBannerWidget" <vehicleBanner class="mb-3" cms-widget-name="VehicleBannerWidget" :display-generic-vehicle-image="false" />
:display-generic-vehicle-image="false" /> <siteSubHeader cms-widget-name="SiteSubHeaderWidget" />
<siteSubHeader cms-widget-name="SiteSubHeaderWidget" /> <alert
<alert ref="alertVinNotFound"
ref="alertVinNotFound" v-if="displayVinNotFoundAlert"
v-if="displayVinNotFoundAlert" class="mb-4"
class="mb-4" cmsWidgetName="AlertVinNotFoundWidget"
cmsWidgetName="AlertVinNotFoundWidget" alertClass="alert-danger"
alertClass="alert-danger" v-bind:isDismissible="false" />
v-bind:isDismissible="false" /> <alert
<alert ref="alertMatchedDifferentVehicle"
ref="alertMatchedDifferentVehicle" v-if="displayMatchedDifferentVehicleAlert"
v-if="displayMatchedDifferentVehicleAlert" class="mb-4"
class="mb-4" cmsWidgetName="AlertMatchedDifferentVehicleWidget"
cmsWidgetName="AlertMatchedDifferentVehicleWidget" :manualHeadline="AlertMatchedDifferentVehicleHeader"
:manualHeadline="AlertMatchedDifferentVehicleHeader" :manualCopy="AlertMatchedDifferentVehicleBody"
:manualCopy="AlertMatchedDifferentVehicleBody" alertClass="alert-warning"
alertClass="alert-warning" v-bind:isDismissible="false" />
v-bind:isDismissible="false" /> <alert
<alert ref="alertMatchedTwoIdenticalYMMVehicle"
ref="alertMatchedTwoIdenticalYMMVehicle" v-if="displayMatchedTwoIdenticalYMMVehicleAlert"
v-if="displayMatchedTwoIdenticalYMMVehicleAlert" class="mb-4"
class="mb-4" cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget"
cmsWidgetName="AlertMatchedTwoIdenticalYMMVehicleWidget" :manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader"
:manualHeadline="AlertMatchedTwoIdenticalYMMVehicleHeader" :manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody"
:manualCopy="AlertMatchedTwoIdenticalYMMVehicleBody" alertClass="alert-warning"
alertClass="alert-warning" v-bind:isDismissible="false" />
v-bind:isDismissible="false" /> <textboxQuestion
<textboxQuestion cmsWidgetName="LicensePlateNumberQuestionWidget"
cmsWidgetName="LicensePlateNumberQuestionWidget" v-model="licensePlate"
v-model="licensePlate" isRequired
isRequired disableAutoFill
disableAutoFill id="license-plate-question-wrapper"
id="license-plate-question-wrapper" inputId="license-plate-question"
inputId="license-plate-question" validationRules="license-plate-required" />
validationRules="license-plate-required" /> <dropdownQuestion
<dropdownQuestion cmsWidgetName="StateQuestionWidget"
cmsWidgetName="StateQuestionWidget" v-model="licenseState"
v-model="licenseState" ref="state"
ref="state" inputId="8fdf9dc2e13e430eb57529499dceb3eb"
inputId="8fdf9dc2e13e430eb57529499dceb3eb" :options="stateOptions"
:options="stateOptions" disableAutoFill
disableAutoFill validationRules="state-required"
validationRules="state-required" class="mt-4" />
class="mt-4" /> <siteFooter
<siteFooter :isForwardActionDisabled="!meta.valid"
:isForwardActionDisabled="!meta.valid" cms-widget-name="SiteFooterWidget"
cms-widget-name="SiteFooterWidget" @back-clicked="backButtonAction"
@back-clicked="backButtonAction" @forward-clicked="forwardButtonAction"
@forward-clicked="forwardButtonAction" ref="siteFooter" />
ref="siteFooter" /> </div>
</div> </div>
</div> </div>
</Form> </div>
</div>
</div>
</div>
</Form>
</template> </template>
<script> <script>
// Import Supporting Files // Import Supporting Files
@ -92,55 +96,55 @@ defineRule("license-plate-required", required(errorMessages.LICENSE_PLATE_REQUIR
defineRule("state-required", required(errorMessages.STATE_REQUIRED)); defineRule("state-required", required(errorMessages.STATE_REQUIRED));
export default { export default {
name: 'license-plate-lookup', name: 'license-plate-lookup',
mixins: [baseFormMixin, vinPagesMixin], mixins: [baseFormMixin, vinPagesMixin],
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{ {
resultKey: 'cmsContent', resultKey: 'cmsContent',
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
}); });
},
data() {
return {
activeVehicleLookupAlertType: null,
vehicleFromLookup: null,
licensePlate: null,
licenseState: useMainStore().order.customer.address.state,
displayVinNotFoundAlert: false,
displayMatchedDifferentVehicleAlert: false,
displayMatchedTwoIdenticalYMMVehicleAlert: false,
previouslyEnteredCarId: "",
isCarIdDifferent: false,
customAlertData: {},
isSelectedGlassAvailableForVehicle: true,
forwardButtonCarStyle:"",
};
},
methods: {
arePagePrerequisitesValid() {
return this.mainStore.order.vehicle.carId !== null;
}, },
loadDefaultsFromStore() { data() {
this.customerQuestions = this.mainStore.customerData.addressQuestions.state; return {
activeVehicleLookupAlertType: null,
vehicleFromLookup: null,
licensePlate: null,
licenseState: useMainStore().order.customer.address.state,
displayVinNotFoundAlert: false,
displayMatchedDifferentVehicleAlert: false,
displayMatchedTwoIdenticalYMMVehicleAlert: false,
previouslyEnteredCarId: "",
isCarIdDifferent: false,
customAlertData: {},
isSelectedGlassAvailableForVehicle: true,
forwardButtonCarStyle:"",
};
}, },
backButtonAction() { methods: {
// route to move backwards arePagePrerequisitesValid() {
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); return this.mainStore.order.vehicle.carId !== null;
}, },
attachCustomEvents() { loadDefaultsFromStore() {
this.customerQuestions = this.mainStore.customerData.addressQuestions.state;
},
backButtonAction() {
// route to move backwards
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
attachCustomEvents() {
this.prependActionToMethod(this, this.forwardButtonAction, () => { this.prependActionToMethod(this, this.forwardButtonAction, () => {
this.pushEventToGA( this.pushEventToGA(
this.$route.query[this.queryStrings.ISS_PAGE], this.$route.query[this.queryStrings.ISS_PAGE],
@ -149,179 +153,186 @@ export default {
true true
); );
}); });
},
// NOTE: If form is not valid, this method is not called when 'Continue' button is clicked
async forwardButtonAction() {
this.resetWarningsAndErrors();
// Lookup VIN
const vinLookupResponse = await useMainStore().lookupVinByPlate(
this.licensePlate, this.licenseState);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "vinLookupResponse",
promise: vinLookupResponse,
}, },
]; // NOTE: If form is not valid, this method is not called when 'Continue' button is clicked
async forwardButtonAction() {
this.resetWarningsAndErrors();
const resultMap = await settleAllPromises(promiseResultMap); // Lookup VIN
const vinLookupResponse = await useMainStore().lookupVinByPlate(
this.licensePlate, this.licenseState);
// No VIN found // Settle promises and get results
if (resultMap.vinLookupResponse.error) { const promiseResultMap = [
this.displayVinNotFoundAlert = true; {
this.$refs.siteFooter.disableForwardButton(); resultKey: "vinLookupResponse",
return this.$refs.siteFooter.removeLoader(); promise: vinLookupResponse,
}; },
];
// Vehicle found from VIN lookup const resultMap = await settleAllPromises(promiseResultMap);
const vehicleFromLookup = resultMap.vinLookupResponse.vehicle;
// Check if the CarId has changed // No VIN found
this.isCarIdDifferent = if (resultMap.vinLookupResponse.error) {
vehicleFromLookup.carId !== useMainStore().order.vehicle.carId; this.displayVinNotFoundAlert = true;
// Handle changing car this.$refs.siteFooter.disableForwardButton();
if ( return this.$refs.siteFooter.removeLoader();
this.isCarIdDifferent && };
vehicleFromLookup.carId !== this.previouslyEnteredCarId
) {
// Display Alert
this.previouslyEnteredCarId = vehicleFromLookup.carId;
this.customAlertData.vehicleInfo = vehicleFromLookup;
if(this.isTwoIdenticalYMMVehicleFound){ // Vehicle found from VIN lookup
this.displayMatchedTwoIdenticalYMMVehicleAlert = true; const vehicleFromLookup = resultMap.vinLookupResponse.vehicle;
this.forwardButtonCarStyle= vehicleFromLookup.style;
}
else{
this.displayMatchedDifferentVehicleAlert = true;
}
this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId( // Check if the CarId has changed
vehicleFromLookup.carId this.isCarIdDifferent =
); vehicleFromLookup.carId !== useMainStore().order.vehicle.carId;
// Handle changing car
if (
this.isCarIdDifferent &&
vehicleFromLookup.carId !== this.previouslyEnteredCarId
) {
// Display Alert
this.previouslyEnteredCarId = vehicleFromLookup.carId;
this.customAlertData.vehicleInfo = vehicleFromLookup;
// Update button "Continue with..." if(this.isTwoIdenticalYMMVehicleFound){
this.$refs.siteFooter.updateButtonText(`Continue with ${vehicleFromLookup.year} ${vehicleFromLookup.make} ${vehicleFromLookup.model} ${this.forwardButtonCarStyle}`); this.displayMatchedTwoIdenticalYMMVehicleAlert = true;
return this.$refs.siteFooter.removeLoader(); this.forwardButtonCarStyle= vehicleFromLookup.style;
} }
else{
this.displayMatchedDifferentVehicleAlert = true;
}
// Save vehicle, license plate, and registration information this.isSelectedGlassAvailableForVehicle = await isGlassAvailableForCarId(
await useMainStore().saveRegistrationLicensePlateLookup( vehicleFromLookup.carId
{ );
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
vehicleInfo: Object.assign(vinLookupResponse.data.vehicle, { vin: vinLookupResponse.data.vin }),
registrationInfo: {
licensePlate: this.licensePlate,
state: this.licenseState,
},
},
false
);
return await this.navigateForward(); // Update button "Continue with..."
}, this.$refs.siteFooter.updateButtonText(`Continue with ${vehicleFromLookup.year} ${vehicleFromLookup.make} ${vehicleFromLookup.model} ${this.forwardButtonCarStyle}`);
async navigateForward() { return this.$refs.siteFooter.removeLoader();
// If a different vehicle is found than the one entered and the selected glass is not available for that vehicle then navigate back to "vehicle-damage" }
// display vehicle changed alert on that page.
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigate(
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
} else {
await this.navigateForwardWithSingleCarMatch();
}
},
resetWarningsAndErrors() {
this.displayVinNotFoundAlert = false;
this.displayMatchedDifferentVehicleAlert = false;
},
},
mounted() {
this.attachCustomEvents();
this.loadDefaultsFromStore();
},
computed: {
AlertMatchedDifferentVehicleHeader() {
return this.getCmsContent(
"AlertMatchedDifferentVehicleWidget",
"HeadlineText"
).replaceAll("{custom:damage}", getDamageString());
},
AlertMatchedDifferentVehicleBody() {
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText") // Save vehicle, license plate, and registration information
await useMainStore().saveRegistrationLicensePlateLookup(
{
isSelectedGlassAvailableForVehicle: this.isSelectedGlassAvailableForVehicle,
vehicleInfo: Object.assign(vinLookupResponse.data.vehicle, { vin: vinLookupResponse.data.vin }),
registrationInfo: {
licensePlate: this.licensePlate,
state: this.licenseState,
},
},
false
);
return await this.navigateForward();
},
async navigateForward() {
// If a different vehicle is found than the one entered and the selected glass is not available for that vehicle then navigate back to "vehicle-damage"
// display vehicle changed alert on that page.
if (this.isCarIdDifferent && !this.isSelectedGlassAvailableForVehicle) {
this.$router.navigate(
this.navigationScenarios.SELECTED_VIN_WITH_MISMATCHED_GLASS,
this.$route,
{},
{ [routerParams.DISPLAY_VEHICLE_CHANGE_ALERT]: true }
);
} else {
await this.navigateForwardWithSingleCarMatch();
}
},
resetWarningsAndErrors() {
this.displayVinNotFoundAlert = false;
this.displayMatchedDifferentVehicleAlert = false;
},
},
mounted() {
this.attachCustomEvents();
this.loadDefaultsFromStore();
},
computed: {
AlertMatchedDifferentVehicleHeader() {
return this.getCmsContent(
"AlertMatchedDifferentVehicleWidget",
"HeadlineText"
).replaceAll("{custom:damage}", getDamageString());
},
AlertMatchedDifferentVehicleBody() {
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
return this.getCmsContent("AlertMatchedDifferentVehicleWidget", "BodyText")
.replaceAll("{custom:damage}", getDamageString()) .replaceAll("{custom:damage}", getDamageString())
.replaceAll("{custom:vinYmmFound}", vinYmmFound) .replaceAll("{custom:vinYmmFound}", vinYmmFound)
.replaceAll("{custom:vinYmmExpected}", vinYmmExpected); .replaceAll("{custom:vinYmmExpected}", vinYmmExpected);
}, },
AlertMatchedTwoIdenticalYMMVehicleHeader() { AlertMatchedTwoIdenticalYMMVehicleHeader() {
return this.getCmsContent( return this.getCmsContent(
"AlertMatchedTwoIdenticalYMMVehicleWidget", "AlertMatchedTwoIdenticalYMMVehicleWidget",
"HeadlineText" "HeadlineText"
).replaceAll("{custom:damage}", getDamageString()); ).replaceAll("{custom:damage}", getDamageString());
}, },
AlertMatchedTwoIdenticalYMMVehicleBody() { AlertMatchedTwoIdenticalYMMVehicleBody() {
const vinYmmsFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`; const vinYmmsFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model} ${this.customAlertData?.vehicleInfo?.style}`;
const vinYmmsExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`; const vinYmmsExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model} ${this.mainStore.order.vehicle.style}`;
return this.getCmsContent("AlertMatchedTwoIdenticalYMMVehicleWidget", "BodyText") return this.getCmsContent("AlertMatchedTwoIdenticalYMMVehicleWidget", "BodyText")
.replaceAll("{custom:damage}", getDamageString()) .replaceAll("{custom:damage}", getDamageString())
.replaceAll("{custom:vinYmmsFound}", vinYmmsFound) .replaceAll("{custom:vinYmmsFound}", vinYmmsFound)
.replaceAll("{custom:vinYmmsExpected}", vinYmmsExpected); .replaceAll("{custom:vinYmmsExpected}", vinYmmsExpected);
}, },
isTwoIdenticalYMMVehicleFound(){ isTwoIdenticalYMMVehicleFound(){
const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`; const vinYmmFound = `${this.customAlertData?.vehicleInfo?.year} ${this.customAlertData?.vehicleInfo?.make} ${this.customAlertData?.vehicleInfo?.model}`;
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`; const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`;
return(vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase()); return(vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase());
},
stateOptions: {
get: function () {
return states;
},
},
}, },
stateOptions: { watch: {
get: function () { licensePlate() {
return states; this.$refs.siteFooter.updateButtonText(
this.getCmsContent("SiteFooterWidget", "ForwardButtonText")
);
},
registrationZipCode() {
this.$refs.siteFooter.updateButtonText(
this.getCmsContent("SiteFooterWidget", "ForwardButtonText")
);
},
}, },
}, components: {
}, Form,
watch: { siteFooter,
licensePlate() { siteHeader,
this.$refs.siteFooter.updateButtonText( siteSubHeader,
this.getCmsContent("SiteFooterWidget", "ForwardButtonText") vehicleBanner,
); textboxQuestion,
}, dropdownQuestion,
registrationZipCode() { alert
this.$refs.siteFooter.updateButtonText( },
this.getCmsContent("SiteFooterWidget", "ForwardButtonText") };
); </script>
},
},
components: {
Form,
siteFooter,
siteHeader,
siteSubHeader,
vehicleBanner,
textboxQuestion,
dropdownQuestion,
alert
},
};
</script>
<style> <style lang="scss" scoped>
.fade-on-route-transition {
margin-bottom: 100px;
}
.page-container-grouped-styles {
overflow: auto;
}
.overflow-scroll { .modal-open {
height: calc(100% - 220px); .page-container-grouped-styles {
overflow-x: hidden !important; overflow: hidden;
} }
#license-plate-question-wrapper .form-test-error { }
/** #license-plate-question-wrapper .form-test-error {
Override extra margin-bottom in the error message in TextboxQuestion /**
*/ Override extra margin-bottom in the error message in TextboxQuestion
margin-bottom: 0 !important; */
} margin-bottom: 0 !important;
</style> }
</style>

View file

@ -1,13 +1,14 @@
<template> <template>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" > <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
<div class="page-container-grouped-styles "> <div class="page-container-grouped-styles">
<siteHeader cmsWidgetName="SiteHeaderWidget"/> <div class="fade-on-route-transition position-relative">
<div class="fade-on-route-transition px-5 overflow-scroll"> <siteHeader cmsWidgetName="SiteHeaderWidget"/>
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" id="sub-header"/> <div class="container-fluid pb-2">
<addressQuestions ref="addressQuestions" v-model="customerQuestions.addressQuestions" includeStreetAddress2="true" id="address-questions-wrapper"/> <div class="row mt-4 px-3">
<div class="row mt-4 "> <div class="col">
<div class="col"> <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" id="sub-header"/>
<textboxQuestion <addressQuestions ref="addressQuestions" v-model="customerQuestions.addressQuestions" includeStreetAddress2="true" id="address-questions-wrapper"/>
<textboxQuestion
inputId="firstNameField" inputId="firstNameField"
cmsWidgetName="PolicyholderFirstNameQuestion" cmsWidgetName="PolicyholderFirstNameQuestion"
v-model="customerQuestions.firstName" v-model="customerQuestions.firstName"
@ -15,11 +16,7 @@
ref="policyHolderFirstName" ref="policyHolderFirstName"
disableAutoFill disableAutoFill
validationRules="first-name-required" /> validationRules="first-name-required" />
</div> <textboxQuestion
</div>
<div class="row mt-4 mb-2">
<div class="col">
<textboxQuestion
inputId="lastNameField" inputId="lastNameField"
cmsWidgetName="PolicyholderLastNameQuestion" cmsWidgetName="PolicyholderLastNameQuestion"
v-model="customerQuestions.lastName" v-model="customerQuestions.lastName"
@ -27,15 +24,16 @@
ref="policyHolderLastName" ref="policyHolderLastName"
disableAutoFill disableAutoFill
validationRules="last-name-required" /> validationRules="last-name-required" />
</div> </div>
</div> </div>
<siteFooter <siteFooter
cmsWidgetName="SiteFooterWidget" cmsWidgetName="SiteFooterWidget"
ref="siteFooter" ref="siteFooter"
:isForwardActionDisabled="!meta.valid" :isForwardActionDisabled="!meta.valid"
@ForwardClicked="forwardButtonAction" @ForwardClicked="forwardButtonAction"
@back-clicked="backButtonAction" @back-clicked="backButtonAction"
/> />
</div>
</div> </div>
</div> </div>
</Form> </Form>
@ -60,7 +58,7 @@ import { useMainStore } from '@/store';
//define validation rules //define validation rules
defineRule("first-name-required", required(errorMessages.POLICYHOLDER_FIRST_NAME_REQUIRED)); defineRule("first-name-required", required(errorMessages.POLICYHOLDER_FIRST_NAME_REQUIRED));
defineRule("last-name-required", required(errorMessages.POLICYHOLDER_LAST_NAME_REQUIRED)); defineRule("last-name-required", required(errorMessages.POLICYHOLDER_LAST_NAME_REQUIRED));
export default { export default {
name: "policy-holder-details", name: "policy-holder-details",
mixins: [BaseFormMixin], mixins: [BaseFormMixin],
@ -73,94 +71,101 @@ export default {
const mainStore = useMainStore(); const mainStore = useMainStore();
return { mainStore }; return { mainStore };
}, },
async beforeRouteEnter(to, from, next) async beforeRouteEnter(to, from, next)
{ {
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},];
//use resultMap to populate layout content.
let resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
methods:
{ {
resultKey: "cmsContent", backButtonAction() {
promise: cmsContentPromise, this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},]; },
forwardButtonAction()
//use resultMap to populate layout content. {
let resultMap = await settleAllPromises(promiseResultMap); this.mainStore.updatePolicyHolderDetails(this.customerQuestions);
return this.navigateForward();
},
next((vm) => { navigateForward() {
vm.setCmsContent(resultMap.cmsContent); this.$router.navigate(
}); this.navigationScenarios.CLICKED_FORWARD_POLICY_HOLDER_DETAILS,
}, this.$route
methods: );
},
getPolicyHolderDetailsFromStore() {
return {
addressQuestions :
{
streetAddress: this.mainStore.order.customer.address.streetAddress,
streetAddress2: this.mainStore.order.customer.address.streetAddress2,
city: this.mainStore.order.customer.address.city,
state: this.mainStore.order.customer.address.state,
zipCode: this.mainStore.order.customer.address.zipCode,
},
firstName : this.mainStore.order.customer.firstName,
lastName : this.mainStore.order.customer.lastName,
}
},
},
components: {
siteHeader,
siteSubHeader,
textboxQuestion,
addressQuestions,
siteFooter,
Form,
},
}
</script>
<style lang="scss">
.fade-on-route-transition {
height: calc(100% - 120px);
overflow: scroll;
overflow-x: hidden;
}
.modal-open {
.fade-on-route-transition {
overflow: hidden;
}
}
.alert.alert-warning
{ {
backButtonAction() { margin-top: 20px;
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); }
},
forwardButtonAction()
{
this.mainStore.updatePolicyHolderDetails(this.customerQuestions);
return this.navigateForward();
},
navigateForward() { #sub-header p {
this.$router.navigate( font-size: 16px;
this.navigationScenarios.CLICKED_FORWARD_POLICY_HOLDER_DETAILS, line-height: 26px;
this.$route color: #4D5151;
); }
},
getPolicyHolderDetailsFromStore() {
return {
addressQuestions :
{
streetAddress: this.mainStore.order.customer.address.streetAddress,
streetAddress2: this.mainStore.order.customer.address.streetAddress2,
city: this.mainStore.order.customer.address.city,
state: this.mainStore.order.customer.address.state,
zipCode: this.mainStore.order.customer.address.zipCode,
},
firstName : this.mainStore.order.customer.firstName,
lastName : this.mainStore.order.customer.lastName,
}
},
},
components: {
siteHeader,
siteSubHeader,
textboxQuestion,
addressQuestions,
siteFooter,
Form,
},
}
</script>
<style lang="scss">
.overflow-scroll {
height: calc(100% - 168px);
overflow-X: hidden !important;
}
.alert.alert-warning
{
margin-top: 20px;
}
#sub-header p { #address-questions-wrapper {
font-size: 16px; margin-top: 24px;
line-height: 26px; }
color: #4D5151;
}
#address-questions-wrapper { #address-questions-wrapper .alert.heading {
margin-top: 24px; line-height: 24px;
} }
#address-questions-wrapper .alert.heading { #address-questions-wrapper .form-test-error {
line-height: 24px; line-height: 24px;
} }
</style>
#address-questions-wrapper .form-test-error {
line-height: 24px;
}
</style>

View file

@ -1,35 +1,43 @@
<template> <template>
<Form @submit="onSubmit" @invalidSubmit="onInvalidSubmit" v-slot="{ meta }"> <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
<div class="page-container-grouped-styles overflow-auto"> <div class="page-container-grouped-styles">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition position-relative">
<siteSubHeader cmsWidgetName="SiteSubHeader" id="sub-header" /> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="fade-on-route-transition sub-container make-tall overflow-scroller px-5"> <div class="select-car">
<div v-html="ProviderPreferenceHeaderText" class="text-center mb-5 modal-link" ></div> <div class="container-fluid pb-2">
<div <div class="row px-3">
v-html="ProviderPreferenceBodyText" <div class="col">
class="mt-0 body-text" <div class="select-car-form rounded">
></div> <div v-html="ProviderPreferenceHeaderText" class="text-center mb-4 modal-link" ></div>
<shoppreferenceModal cmsWidgetName="ShopPreferenceDrawer" /> <div
v-html="ProviderPreferenceBodyText"
class="mt-0 body-text"
></div>
<shoppreferenceModal cmsWidgetName="ShopPreferenceDrawer" />
<buttonQuestion
cmsWidgetName="ServiceLocationQuestion"
:questionText="questionText"
:answers="answersFromCms"
buttonTypeString="listButton"
isRequired
v-model="SelectedshopLocation"
validationRules="questions-required" />
<buttonQuestion <siteFooter
cmsWidgetName="ServiceLocationQuestion" cmsWidgetName="SiteFooterWidget"
:questionText="questionText" :isForwardActionDisabled="isForwardActionDisabled"
:answers="answersFromCms" @backClicked="backButtonAction"
buttonTypeString="listButton" @forwardClicked="forwardButtonAction"
isRequired ref="siteFooter"
v-model="SelectedshopLocation" />
validationRules="questions-required" /> </div>
</div>
<siteFooter </div>
cmsWidgetName="SiteFooterWidget" </div>
:isForwardActionDisabled="isForwardActionDisabled" </div>
@backClicked="backButtonAction" </div>
@forwardClicked="forwardButtonAction" </div>
ref="siteFooter" </Form>
/>
</div>
</div>
</Form>
</template> </template>
<script> <script>
// Import Supporting Files // Import Supporting Files
@ -50,77 +58,85 @@ import shoppreferenceModal from '@/layouts/provider-preference/shoppreference-mo
// DEFINE VALIDATION RULES // DEFINE VALIDATION RULES
defineRule("questions-required", required(errorMessages.OPTION_REQUIRED)); defineRule("questions-required", required(errorMessages.OPTION_REQUIRED));
export default { export default {
name: "provider-preference", name: "provider-preference",
mixins: [baseFormMixin], mixins: [baseFormMixin],
components: { components: {
siteFooter, siteFooter,
siteHeader, siteHeader,
siteSubHeader, siteSubHeader,
Form, Form,
shoppreferenceModal, shoppreferenceModal,
buttonQuestion buttonQuestion
},
data() {
return {
SelectedshopLocation : null,
};
},
async beforeRouteEnter(to, from, next) {
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
computed: {
isForwardActionDisabled() {
return this.SelectedshopLocation === null;
}, },
ProviderPreferenceHeaderText(){ data() {
return this.getCmsContent("ProviderPreference", "HeaderText"); return {
SelectedshopLocation : null,
};
}, },
ProviderPreferenceBodyText(){ async beforeRouteEnter(to, from, next) {
return this.getCmsContent("ProviderPreference", "BodyText"); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
}, },
questionText() { computed: {
isForwardActionDisabled() {
return this.SelectedshopLocation === null;
},
ProviderPreferenceHeaderText(){
return this.getCmsContent("ProviderPreference", "HeaderText");
},
ProviderPreferenceBodyText(){
return this.getCmsContent("ProviderPreference", "BodyText");
},
questionText() {
return this.getCmsContent("ServiceLocationQuestion", "QuestionText"); return this.getCmsContent("ServiceLocationQuestion", "QuestionText");
}, },
answersFromCms() { answersFromCms() {
return this.getCmsContent("ServiceLocationQuestion", "Answers"); return this.getCmsContent("ServiceLocationQuestion", "Answers");
}, },
},
methods: {
arePagePrerequisiteValid() {
return true;
}, },
backButtonAction() { methods: {
/** arePagePrerequisiteValid() {
* this.navigationScenarios comes from base-mixin return true;
*/ },
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); backButtonAction() {
/**
* this.navigationScenarios comes from base-mixin
*/
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
forwardButtonAction() {
if(this.SelectedshopLocation == "Schedule with Safelite")
{
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, this.$route);
}
},
resetDependentState() {},
}, },
forwardButtonAction() {
if(this.SelectedshopLocation == "Schedule with Safelite")
{
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD_WITH_SAFELITE, this.$route);
}
},
resetDependentState() {},
},
}; };
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.overflow-scroller { .fade-on-route-transition {
height: calc(100% - 220px) !important; margin-bottom: 100px;
overflow-X: hidden !important; }
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
} }
#sub-header span{ #sub-header span{
color: $black; color: $black;
@ -138,9 +154,9 @@ margin-bottom: 0.5rem;
font-weight: 500; font-weight: 500;
} }
.question-text { .question-text {
margin-top: 0; margin-top: 0;
& > span { & > span {
text-align: left; text-align: left;
} }
} }
</style> </style>

View file

@ -1,25 +1,32 @@
<template> <template>
<div> <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
<Form @submit="onSubmit" @invalidSubmit="onInvalidSubmit" v-slot="{ meta }"> <div class="page-container-grouped-styles">
<div class="page-container-grouped-styles overflow-auto"> <div class="fade-on-route-transition position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" /> <div class="select-car">
<div class="fade-on-route-transition sub-container make-tall px-5"> <div class="container-fluid pb-2">
<p>Placeholder for service-location page</p> <div class="row px-3">
<siteFooter <div class="col">
cmsWidgetName="SiteFooterWidget" <div class="select-car-form rounded">
:isForwardActionDisabled="!meta.valid" <p>Placeholder for service-location page</p>
@backClicked="backButtonAction" <siteFooter
@forwardClicked="forwardButtonAction" cmsWidgetName="SiteFooterWidget"
ref="siteFooter" :isForwardActionDisabled="!meta.valid"
/> @backClicked="backButtonAction"
</div> @forwardClicked="forwardButtonAction"
</div> ref="siteFooter"
</Form> />
</div> </div>
</template> </div>
<script> </div>
// Import Supporting Files </div>
</div>
</div>
</div>
</Form>
</template>
<script>
// Import Supporting Files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper"; import { settleAllPromises } from "@/helpers/layout-helper";
// Import Component // Import Component
@ -29,43 +36,58 @@ import siteFooter from "@/iss-components/site-footer/site-footer.vue";
import siteHeader from "@/iss-components/site-header/site-header.vue"; import siteHeader from "@/iss-components/site-header/site-header.vue";
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue"; import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header.vue";
export default { export default {
name: "provider-preference", name: "provider-preference",
mixins: [baseFormMixin], mixins: [baseFormMixin],
components: { components: {
siteFooter, siteFooter,
siteHeader, siteHeader,
siteSubHeader, siteSubHeader,
Form, Form,
},
data() {
return {};
},
async beforeRouteEnter(to, from, next) {
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
methods: {
arePagePrerequisiteValid() {
return true;
}, },
backButtonAction() { data() {
/** return {};
* this.navigationScenarios comes from base-mixin },
*/ async beforeRouteEnter(to, from, next) {
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results
const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
methods: {
arePagePrerequisiteValid() {
return true;
},
backButtonAction() {
/**
* this.navigationScenarios comes from base-mixin
*/
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
async forwardButtonAction() {},
resetDependentState() {},
}, },
async forwardButtonAction() {},
resetDependentState() {},
},
}; };
</script> </script>
<style lang="scss" scoped>
.fade-on-route-transition {
margin-bottom: 100px;
}
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
}
</style>

View file

@ -1,58 +1,64 @@
<template> <template>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }"> <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
<div class="page-container-grouped-styles vehicle-damage"> <div class="page-container-grouped-styles">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition position-relative">
<div class="fade-on-route-transition sub-container overflow-scroll px-5"> <siteHeader cmsWidgetName="SiteHeaderWidget"/>
<alert <div class="container-fluid pb-2">
ref="vehicleChangeAlert" <div class="row mt-4 px-3">
v-if="shouldDisplayVehicleChangeAlert" <div class="col">
class="mt-5 mb-0" <alert
cmsWidgetName="VehicleChangeAlert" ref="vehicleChangeAlert"
alertClass="alert-warning" v-if="shouldDisplayVehicleChangeAlert"
:isDismissible="false" /> class="mt-5 mb-0"
<vehicleBanner cmsWidgetName="VehicleChangeAlert"
class="mb-3" alertClass="alert-warning"
cmsWidgetName="VehicleBannerWidget" :isDismissible="false" />
:displayGenericVehicleImage="false" /> <vehicleBanner
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" /> class="mb-3"
<damageLocationQuestion cmsWidgetName="VehicleBannerWidget"
ref="damageLocation" :displayGenericVehicleImage="false" />
cmsWidgetName="DamageLocationQuestion" <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
v-model="selectedDamageLocations" <damageLocationQuestion
groupName="DamageLocationQuestion" /> ref="damageLocation"
<windshieldOptions cmsWidgetName="DamageLocationQuestion"
ref="windshieldOptions" v-model="selectedDamageLocations"
v-model="selectedWindshieldOptions" groupName="DamageLocationQuestion" />
:hasRepairReplaceConflict="hasRepairReplaceConflict" <windshieldOptions
:hasSplitSingleConflict="hasSplitSingleConflict" ref="windshieldOptions"
:selectedDamageLocations="selectedDamageLocations" /> v-model="selectedWindshieldOptions"
<alert :hasRepairReplaceConflict="hasRepairReplaceConflict"
v-if="hasRepairReplaceConflict" :hasSplitSingleConflict="hasSplitSingleConflict"
class="my-5" :selectedDamageLocations="selectedDamageLocations" />
cmsWidgetName="HasReplacementConflict" <alert
alertClass="alert-danger" v-if="hasRepairReplaceConflict"
:isDismissible="false" /> class="my-5"
<sideDoorOptions cmsWidgetName="HasReplacementConflict"
ref="sideDoorOptions" alertClass="alert-danger"
cmsWidgetName="SideDoorSideQuestion" :isDismissible="false" />
groupName="SideDoorSideQuestion" <sideDoorOptions
v-model="sideDoorOptionsData" ref="sideDoorOptions"
v-show="!hasRepairReplaceConflict" cmsWidgetName="SideDoorSideQuestion"
:selectedDamageLocations="selectedDamageLocations" /> groupName="SideDoorSideQuestion"
<replaceOptionsQuestion v-model="sideDoorOptionsData"
ref="backGlassOptions" v-show="!hasRepairReplaceConflict"
cmsWidgetName="RearReplaceOptionsQuestion" :selectedDamageLocations="selectedDamageLocations" />
:isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict" <replaceOptionsQuestion
v-model="selectedRearReplaceOptions" ref="backGlassOptions"
groupName="BackGlassReplaceOptionsQuestion" cmsWidgetName="RearReplaceOptionsQuestion"
validationRules="replace-options-required" /> :isAvailable="isRearWindowDamageLocation && !hasRepairReplaceConflict"
<site-footer v-model="selectedRearReplaceOptions"
cmsWidgetName="SiteFooterWidget" groupName="BackGlassReplaceOptionsQuestion"
:isForwardActionDisabled="!meta.valid" validationRules="replace-options-required" />
@backClicked="backButtonAction" <site-footer
@forwardClicked="forwardButtonAction" cmsWidgetName="SiteFooterWidget"
ref="siteFooter" :isForwardActionDisabled="!meta.valid"
/> @backClicked="backButtonAction"
@forwardClicked="forwardButtonAction"
ref="siteFooter"
/>
</div>
</div>
</div>
</div> </div>
</div> </div>
</Form> </Form>
@ -207,7 +213,7 @@ export default {
}) })
) { ) {
windShieldOptions.selectedWindshieldDamageType = windShieldOptions.selectedWindshieldDamageType =
damageLocationsSelected.REPLACE; damageLocationsSelected.REPLACE;
windShieldOptions.selectedWindshieldReplaceOptions.push( windShieldOptions.selectedWindshieldReplaceOptions.push(
damageLocationsSelected.SINGLE damageLocationsSelected.SINGLE
); );
@ -222,7 +228,7 @@ export default {
}) })
) { ) {
windShieldOptions.selectedWindshieldDamageType = windShieldOptions.selectedWindshieldDamageType =
damageLocationsSelected.REPLACE; damageLocationsSelected.REPLACE;
windShieldOptions.selectedWindshieldReplaceOptions.push( windShieldOptions.selectedWindshieldReplaceOptions.push(
damageLocationsSelected.DRIVER damageLocationsSelected.DRIVER
); );
@ -237,7 +243,7 @@ export default {
}) })
) { ) {
windShieldOptions.selectedWindshieldDamageType = windShieldOptions.selectedWindshieldDamageType =
damageLocationsSelected.REPLACE; damageLocationsSelected.REPLACE;
windShieldOptions.selectedWindshieldReplaceOptions.push( windShieldOptions.selectedWindshieldReplaceOptions.push(
damageLocationsSelected.PASSENGER damageLocationsSelected.PASSENGER
); );
@ -302,147 +308,147 @@ export default {
async forwardButtonAction() { async forwardButtonAction() {
await this.mainStore.saveVehicleDamage(this.isWindshieldRepair, await this.mainStore.saveVehicleDamage(this.isWindshieldRepair,
this.selectedGlassToReplace(), this.selectedGlassToReplace(),
this.selectedWindshieldOptions.selectedWindshieldChipCount); this.selectedWindshieldOptions.selectedWindshieldChipCount);
return this.navigateForward(); return this.navigateForward();
}, },
navigateForward() { navigateForward() {
if (this.mainStore.damage.isRepair) { if (this.mainStore.damage.isRepair) {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
this.$route
);
}
else {
// If vin already exists, navigate directly to vin-lookup
if (this.mainStore.order.vehicle.vin) {
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITH_VIN, this.navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
this.$route
);
} else {
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
this.$route this.$route
); );
} }
} else {
}, // If vin already exists, navigate directly to vin-lookup
if (this.mainStore.order.vehicle.vin) {
selectedGlassToReplace() { this.$router.navigate(
const selectedGlassToReplace = []; this.navigationScenarios.CLICKED_FORWARD_WITH_VIN,
if (this.isWindshieldDamageLocation && !this.isWindshieldRepair) { this.$route
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach( );
(wsItem) => { } else {
selectedGlassToReplace.push({ this.$router.navigate(
glassLocation: damageLocationsSelected.WINDSHIELD, this.navigationScenarios.CLICKED_FORWARD_WITHOUT_VIN,
glassName: wsItem, this.$route
}); );
} }
); }
} },
if (this.isDriverSideReplace) { selectedGlassToReplace() {
this.sideDoorOptionsData.selectedDriverSideReplaceOptions.forEach((driverItem) => { const selectedGlassToReplace = [];
selectedGlassToReplace.push({ if (this.isWindshieldDamageLocation && !this.isWindshieldRepair) {
glassLocation: damageLocationsSelected.DRIVER, this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach(
glassName: driverItem, (wsItem) => {
selectedGlassToReplace.push({
glassLocation: damageLocationsSelected.WINDSHIELD,
glassName: wsItem,
});
}
);
}
if (this.isDriverSideReplace) {
this.sideDoorOptionsData.selectedDriverSideReplaceOptions.forEach((driverItem) => {
selectedGlassToReplace.push({
glassLocation: damageLocationsSelected.DRIVER,
glassName: driverItem,
});
}); });
}
if (this.isPassengerSideReplace) {
this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach(
(passengerItem) => {
selectedGlassToReplace.push({
glassLocation: damageLocationsSelected.PASSENGER,
glassName: passengerItem,
});
}
);
}
if (this.isRearWindowDamageLocation) {
selectedGlassToReplace.push({
glassLocation: damageLocationsSelected.REAR,
glassName: this.selectedRearReplaceOptions,
});
}
return selectedGlassToReplace;
},
},
computed: {
isWindshieldDamageLocation() {
return this.selectedDamageLocations.some((selectedDamages) => {
return selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD;
}); });
} },
isSideDoorDamageLocation() {
if (this.isPassengerSideReplace) { return this.selectedDamageLocations.some((selectedDamages) => {
this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach( return selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR;
(passengerItem) => {
selectedGlassToReplace.push({
glassLocation: damageLocationsSelected.PASSENGER,
glassName: passengerItem,
});
}
);
}
if (this.isRearWindowDamageLocation) {
selectedGlassToReplace.push({
glassLocation: damageLocationsSelected.REAR,
glassName: this.selectedRearReplaceOptions,
}); });
} },
isRearWindowDamageLocation() {
return selectedGlassToReplace; return this.selectedDamageLocations.some((selectedDamages) => {
}, return selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW;
}, });
computed: { },
isWindshieldDamageLocation() { isWindshieldRepair() {
return this.selectedDamageLocations.some((selectedDamages) => { return (
return selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD; this.isWindshieldDamageLocation &&
}); this.selectedWindshieldOptions.selectedWindshieldDamageType ===
},
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 damageLocationsSelected.REPAIR
); );
}, },
isDriverSideReplace() { isDriverSideReplace() {
if (!this.isSideDoorDamageLocation) return false; if (!this.isSideDoorDamageLocation) return false;
return this.sideDoorOptionsData.selectedDoorSides.some((selectedDriverSide) => { return this.sideDoorOptionsData.selectedDoorSides.some((selectedDriverSide) => {
return selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE; return selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE;
}); });
}, },
isPassengerSideReplace() { isPassengerSideReplace() {
if (!this.isSideDoorDamageLocation) return false; if (!this.isSideDoorDamageLocation) return false;
return this.sideDoorOptionsData.selectedDoorSides.some((selectedPassengerSide) => { return this.sideDoorOptionsData.selectedDoorSides.some((selectedPassengerSide) => {
return selectedPassengerSide.toUpperCase() === damageLocationsCms.PASSENGERSIDE; return selectedPassengerSide.toUpperCase() === damageLocationsCms.PASSENGERSIDE;
}); });
}, },
hasRepairReplaceConflict() { hasRepairReplaceConflict() {
return ( return (
this.isWindshieldDamageLocation && this.isWindshieldDamageLocation &&
this.selectedDamageLocations.length > 1 && this.selectedDamageLocations.length > 1 &&
this.isWindshieldRepair this.isWindshieldRepair
); );
}, },
hasSplitSingleConflict() { hasSplitSingleConflict() {
if ( if (
!this.selectedDamageLocations?.includes("Windshield") || !this.selectedDamageLocations?.includes("Windshield") ||
this.selectedWindshieldOptions.selectedWindshieldDamageType === this.selectedWindshieldOptions.selectedWindshieldDamageType ===
damageLocationsSelected.REPAIR || damageLocationsSelected.REPAIR ||
!this.selectedWindshieldOptions.selectedWindshieldReplaceOptions !this.selectedWindshieldOptions.selectedWindshieldReplaceOptions
) )
return false; return false;
return ( return (
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
(selectedSingleWindshield) => { (selectedSingleWindshield) => {
return ( return (
selectedSingleWindshield.toUpperCase() === selectedSingleWindshield.toUpperCase() ===
damageLocationsSelected.SINGLE.toUpperCase() damageLocationsSelected.SINGLE.toUpperCase()
); );
} }
) && ) &&
(this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( (this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
(selectedDriverWindshield) => { (selectedDriverWindshield) => {
return ( return (
selectedDriverWindshield.toUpperCase() === selectedDriverWindshield.toUpperCase() ===
damageLocationsSelected.DRIVER.toUpperCase() damageLocationsSelected.DRIVER.toUpperCase()
); );
} }
) || ) ||
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some( this.selectedWindshieldOptions.selectedWindshieldReplaceOptions?.some(
(selectedPassengerWindshield) => { (selectedPassengerWindshield) => {
return ( return (
@ -451,31 +457,39 @@ export default {
); );
} }
)) ))
); );
},
shouldDisplayVehicleChangeAlert() {
return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT];
}
}, },
shouldDisplayVehicleChangeAlert() {
return this.$route.params[this.routerParams.DISPLAY_VEHICLE_CHANGE_ALERT];
}
},
components: { components: {
siteHeader, siteHeader,
siteFooter, siteFooter,
vehicleBanner, vehicleBanner,
siteSubHeader, siteSubHeader,
sideDoorOptions, sideDoorOptions,
damageLocationQuestion, damageLocationQuestion,
windshieldOptions, windshieldOptions,
replaceOptionsQuestion, replaceOptionsQuestion,
Form, Form,
alert, alert,
}, },
}; };
</script> </script>
<style lang="scss">
.overflow-scroll { <style lang="scss" scoped>
height: calc(100% - 180px); .fade-on-route-transition {
overflow-X: hidden !important; margin-bottom: 100px;
}
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
} }
</style> </style>

View file

@ -1,36 +1,25 @@
<template> <template>
<Form <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit">
@submit="onSubmit" <div class="page-container-grouped-styles">
@invalid-submit="onInvalidSubmit" <div class="fade-on-route-transition position-relative">
> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="page-container-grouped-styles vehicle-lookup"> <div class="select-car">
<SiteHeader <div class="container-fluid pb-2">
cms-widget-name="SiteHeaderWidget" <div class="row px-3">
/> <div class="col">
<div class="fade-on-route-transition sub-container overflow-scroll container gx-0 px-5"> <div class="select-car-form rounded">
<VehicleBanner <VehicleBanner class="mb-3" cms-widget-name="VehicleBannerWidget" :display-generic-vehicle-image="false" />
class="mb-3" <SiteSubHeader cms-widget-name="SiteSubHeaderWidget" />
cms-widget-name="VehicleBannerWidget" <VinLookupMethods v-model="selectedVinLookupMethod" cms-widget-name="VINLookupMethod" group-name="VinLookupMethods" ref="VinLookupMethods" />
:display-generic-vehicle-image="false" <SiteFooter cms-widget-name="SiteFooterWidget" :is-forward-action-disabled="isForwardActionDisabled" @back-clicked="backButtonAction" @forward-clicked="forwardButtonAction" />
/> </div>
<SiteSubHeader </div>
cms-widget-name="SiteSubHeaderWidget" </div>
/> </div>
<VinLookupMethods </div>
v-model="selectedVinLookupMethod" </div>
cms-widget-name="VINLookupMethod" </div>
group-name="VinLookupMethods" </Form>
ref="VinLookupMethods"
/>
<SiteFooter
cms-widget-name="SiteFooterWidget"
:is-forward-action-disabled="isForwardActionDisabled"
@back-clicked="backButtonAction"
@forward-clicked="forwardButtonAction"
/>
</div>
</div>
</Form>
</template> </template>
<script> <script>
// Import Supporting Files // Import Supporting Files
@ -49,78 +38,86 @@ import VehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import VinLookupMethods from './vin-lookup-methods/vin-lookup-methods.vue'; import VinLookupMethods from './vin-lookup-methods/vin-lookup-methods.vue';
export default { export default {
name: 'vehicle-lookup', name: 'vehicle-lookup',
mixins: [BaseFormMixin], mixins: [BaseFormMixin],
components: { components: {
Form, Form,
SiteFooter, SiteFooter,
SiteHeader, SiteHeader,
SiteSubHeader, SiteSubHeader,
VehicleBanner, VehicleBanner,
VinLookupMethods, VinLookupMethods,
}, },
data() { data() {
return { return {
selectedVinLookupMethod: null, selectedVinLookupMethod: null,
}; };
}, },
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{ {
resultKey: 'cmsContent', resultKey: 'cmsContent',
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.$refs.VinLookupMethods.initializeComponent(); vm.$refs.VinLookupMethods.initializeComponent();
}); });
},
computed: {
isForwardActionDisabled() {
return this.selectedVinLookupMethod === null;
}, },
}, computed: {
methods: { isForwardActionDisabled() {
arePagePrerequisiteValid() { return this.selectedVinLookupMethod === null;
return true; },
}, },
backButtonAction() { methods: {
/** arePagePrerequisiteValid() {
* this.navigationScenarios comes from base-mixin return true;
*/ },
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); backButtonAction() {
/**
* this.navigationScenarios comes from base-mixin
*/
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
forwardButtonAction() {
switch (this.selectedVinLookupMethod) {
case vinLookupMethodSelections.MANUALVIN:
useMainStore().updateVehicleVin(null);
this.$router.navigate(this.navigationScenarios.SELECTED_MANUAL_VIN, this.$route);
break;
case vinLookupMethodSelections.LICENSEPLATE:
this.$router.navigate(this.navigationScenarios.SELECTED_LICENSE_PLATE, this.$route);
break;
case vinLookupMethodSelections.HOMEADDRESS:
this.$router.navigate(this.navigationScenarios.SELECTED_HOME_ADDRESS, this.$route);
break;
default:
break;
}
},
resetDependentState() {},
}, },
forwardButtonAction() {
switch (this.selectedVinLookupMethod) {
case vinLookupMethodSelections.MANUALVIN:
useMainStore().updateVehicleVin(null);
this.$router.navigate(this.navigationScenarios.SELECTED_MANUAL_VIN, this.$route);
break;
case vinLookupMethodSelections.LICENSEPLATE:
this.$router.navigate(this.navigationScenarios.SELECTED_LICENSE_PLATE, this.$route);
break;
case vinLookupMethodSelections.HOMEADDRESS:
this.$router.navigate(this.navigationScenarios.SELECTED_HOME_ADDRESS, this.$route);
break;
default:
break;
}
},
resetDependentState() {},
},
}; };
</script> </script>
<style lang="scss">
.overflow-scroll { <style lang="scss" scoped>
height: calc(100% - 180px); .fade-on-route-transition {
overflow-X: hidden !important; margin-bottom: 100px;
}
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
} }
</style> </style>

View file

@ -1,51 +1,47 @@
<template> <template>
<div class="page-container-grouped-styles"> <div class="page-container-grouped-styles position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition position-relative">
<div class="select-car"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="select-car-form rounded text-center"> <div class="select-car">
<vehicleBanner class="mb-3" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="true"/> <div class="container-fluid pb-2">
<siteSubHeader <div class="row">
cmsWidgetName="SiteSubHeaderWidget" <div class="col">
:hasBackButton="true" <div class="select-car-form rounded text-center">
@click-event="backButtonAction" <vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="true" class="mb-3" />
/> <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" :hasBackButton="true" @click-event="backButtonAction" />
<div class="fade-on-route-transition"> <makeQuestion class="px-4" v-model="selectedMake" ref="makeQuestion" cmsWidgetName="VehicleMakeQuestion" />
<makeQuestion <siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter" @back-clicked="backButtonAction" :isForwardButtonHidden="shouldHideForwardButton" />
class="fade-on-route-transition" </div>
v-model="selectedMake" </div>
ref="makeQuestion" </div>
cmsWidgetName="VehicleMakeQuestion" </div>
/> </div>
</div>
<siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter"
@back-clicked="backButtonAction" :isForwardButtonHidden="shouldHideForwardButton" />
</div> </div>
</div>
</div> </div>
</template> </template>
<script> <script>
// Components // Components
import makeQuestion from "@/layouts/vehicle-make/make-question/make-question"; import makeQuestion from "@/layouts/vehicle-make/make-question/make-question";
import siteHeader from "@/iss-components/site-header/site-header"; import siteHeader from "@/iss-components/site-header/site-header";
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header"; import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header";
import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner"; import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner";
import siteFooter from "@/iss-components/site-footer/site-footer"; import siteFooter from "@/iss-components/site-footer/site-footer";
// Supporting files // Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper"; import { settleAllPromises } from "@/helpers/layout-helper";
export default { export default {
name: 'vehicle-make', name: 'vehicle-make',
data() { data() {
return { return {
selectedMake: null, selectedMake: null,
shouldHideForwardButton: true shouldHideForwardButton: true
}; };
}, },
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
const makeQuestionInitialDataPromise = makeQuestion.methods.loadInitialData(); const makeQuestionInitialDataPromise = makeQuestion.methods.loadInitialData();
@ -53,12 +49,12 @@
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{ {
resultKey: "cmsContent", resultKey: "cmsContent",
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
{ {
resultKey: "makeQuestionInitialData", resultKey: "makeQuestionInitialData",
promise: makeQuestionInitialDataPromise, promise: makeQuestionInitialDataPromise,
}, },
]; ];
@ -71,36 +67,51 @@
resultMap.makeQuestionInitialData resultMap.makeQuestionInitialData
); );
}); });
}, },
methods: { methods: {
backButtonAction() { backButtonAction() {
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.CLICKED_BACK, this.navigationScenarios.CLICKED_BACK,
this.$route this.$route
); );
}, },
arePagePrerequisitesValid() { arePagePrerequisitesValid() {
if (this.mainStore.order.vehicle.year){ if (this.mainStore.order.vehicle.year){
return true; return true;
} }
return false; return false;
},
}, },
components: { },
makeQuestion, components: {
siteHeader, makeQuestion,
siteSubHeader, siteHeader,
vehicleBanner, siteSubHeader,
siteFooter vehicleBanner,
}, siteFooter
watch: { },
selectedMake(make) { watch: {
selectedMake(make) {
this.mainStore.updateVehicleMake( make ); this.mainStore.updateVehicleMake( make );
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.SELECTED_MAKE, this.navigationScenarios.SELECTED_MAKE,
this.$route this.$route
); );
}, },
} }
}; };
</script> </script>
<style lang="scss" scoped>
.fade-on-route-transition {
margin-bottom: 80px;
}
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
}
</style>

View file

@ -1,80 +1,80 @@
<template> <template>
<div class="page-container-grouped-styles"> <div class="page-container-grouped-styles position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition position-relative">
<div class="select-car"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="select-car-form rounded text-center"> <div class="select-car">
<vehicleBanner class="mb-3" cmsWidgetName="VehicleBannerWidget" displayGenericVehicleImage /> <div class="container-fluid pb-2">
<siteSubHeader <div class="row">
cmsWidgetName="SiteSubHeaderWidget" <div class="col">
:hasBackButton="true" <div class="select-car-form rounded text-center">
:backButtonAccessibleText="backButtonAccessibleText" <vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="true" class="mb-3" />
@click-event="backButtonAction" <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" :hasBackButton="true" :backButtonAccessibleText="backButtonAccessibleText" @click-event="backButtonAction" />
/> <modelQuestion v-model="selectedModel" ref="modelQuestion" cmsWidgetName="VehicleModelQuestion" class="px-4" />
<div class="fade-on-route-transition"> <siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter" @back-clicked="backButtonAction" :isForwardButtonHidden="shouldHideForwardButton" />
<modelQuestion v-model="selectedModel" ref="modelQuestion" cmsWidgetName="VehicleModelQuestion" /> </div>
</div> </div>
<siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter" </div>
@back-clicked="backButtonAction" :isForwardButtonHidden="shouldHideForwardButton" /> </div>
</div>
</div> </div>
</div>
</div> </div>
</template> </template>
<script> <script>
// Components // Components
import modelQuestion from "@/layouts/vehicle-model/model-question/model-question"; import modelQuestion from "@/layouts/vehicle-model/model-question/model-question";
import siteHeader from "@/iss-components/site-header/site-header"; import siteHeader from "@/iss-components/site-header/site-header";
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header"; import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header";
import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner"; import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner";
import siteFooter from "@/iss-components/site-footer/site-footer"; import siteFooter from "@/iss-components/site-footer/site-footer";
// Supporting files // Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper"; import { settleAllPromises } from "@/helpers/layout-helper";
export default { export default {
name: "vehicle-model", name: "vehicle-model",
data() { data() {
return { return {
selectedModel: null, selectedModel: null,
shouldHideForwardButton: true shouldHideForwardButton: true
}; };
}, },
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
const modelQuestionInitialDataPromise = const modelQuestionInitialDataPromise =
modelQuestion.methods.loadInitialData(); modelQuestion.methods.loadInitialData();
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{ {
resultKey: "cmsContent", resultKey: "cmsContent",
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
{ {
resultKey: "modelQuestionInitialData", resultKey: "modelQuestionInitialData",
promise: modelQuestionInitialDataPromise, promise: modelQuestionInitialDataPromise,
}, },
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.$refs.modelQuestion.initializeComponent( vm.$refs.modelQuestion.initializeComponent(
resultMap.modelQuestionInitialData resultMap.modelQuestionInitialData
); );
}); });
}, },
methods: { methods: {
backButtonAction() { backButtonAction() {
// route to move backwards // route to move backwards
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.CLICKED_BACK, this.navigationScenarios.CLICKED_BACK,
this.$route this.$route
); );
}, },
arePagePrerequisitesValid() arePagePrerequisitesValid()
@ -86,26 +86,44 @@
}, },
}, },
computed: { computed: {
backButtonAccessibleText() backButtonAccessibleText()
{ {
return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText") return this.getCmsContent(this.cmsWidgetName, "BackButtonAccessibleText")
} }
}, },
watch: { watch: {
selectedModel(model) { selectedModel(model) {
this.mainStore.updateVehicleModel( model ); this.mainStore.updateVehicleModel( model );
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.SELECTED_MODEL, this.navigationScenarios.SELECTED_MODEL,
this.$route this.$route
); );
}, },
}, },
components: { components: {
modelQuestion, modelQuestion,
siteHeader, siteHeader,
siteSubHeader, siteSubHeader,
vehicleBanner, vehicleBanner,
siteFooter siteFooter
}, },
}; };
</script> </script>
<style lang="scss" scoped>
.container-fluid {
margin-bottom: 80px;
}
.fade-on-route-transition {
margin-bottom: 80px;
}
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
}
</style>

View file

@ -1,43 +1,53 @@
<template> <template>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm"> <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
<div class="page-container-grouped-styles vehicle-parts small-question-text"> <div class="page-container-grouped-styles">
<siteHeader ref="siteHeader" cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition position-relative">
<div class="fade-on-route-transition sub-container overflow-scroll px-5"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<vehicleBanner <div class="select-car">
class="mb-3" <div class="container-fluid pb-2">
ref="vehicleBanner" <div class="row px-3">
cmsWidgetName="VehicleBannerWidget" <div class="col">
:displayGenericVehicleImage="false" /> <div class="select-car-form rounded">
<siteSubHeader ref="siteSubHeader" cmsWidgetName="SiteSubHeaderWidget" /> <vehicleBanner
<div class="prevent-squish my-5"> class="mb-3"
<div class="row"> ref="vehicleBanner"
<div class="col"> cmsWidgetName="VehicleBannerWidget"
<alert :displayGenericVehicleImage="false" />
class="rounded border-0 shadow-sm" <siteSubHeader ref="siteSubHeader" cmsWidgetName="SiteSubHeaderWidget" />
alertClass="alert-warning" <div class="prevent-squish my-5">
cmsWidgetName="AlertWidget" <div class="row">
:isDismissible="false" <div class="col">
id="vehicle-parts-alert" /> <alert
class="rounded border-0 shadow-sm"
alertClass="alert-warning"
cmsWidgetName="AlertWidget"
:isDismissible="false"
id="vehicle-parts-alert" />
</div>
</div>
</div>
<div v-for="(item, i) in PartsOrQuestions" :key="i">
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
<hr v-if="i > 0" />
<glassPartQuestion
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
:glassLocation="item.glassLocation"
:glassName="item.glassName"
:colorAnswers="item.colorAnswers"
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
</div>
<siteFooter
cmsWidgetName="SiteFooterWidget"
ref="siteFooter"
:isForwardActionDisabled="isForwardActionDisabled"
@backClicked="navigateBack"
@ForwardClicked="forwardButtonAction" />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div v-for="(item, i) in PartsOrQuestions" :key="i">
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
<hr v-if="i > 0" />
<glassPartQuestion
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
:glassLocation="item.glassLocation"
:glassName="item.glassName"
:colorAnswers="item.colorAnswers"
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
</div>
<siteFooter
cmsWidgetName="SiteFooterWidget"
ref="siteFooter"
:isForwardActionDisabled="isForwardActionDisabled"
@backClicked="navigateBack"
@ForwardClicked="forwardButtonAction" />
</div> </div>
</div> </div>
</Form> </Form>
@ -80,152 +90,160 @@ export default {
// Glass Part Question dynamic component // Glass Part Question dynamic component
Object.keys(vm.$refs) Object.keys(vm.$refs)
.filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined) .filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined)
.forEach((c) => .forEach((c) =>
vm.$refs[c][0].initializeComponent({ vm.$refs[c][0].initializeComponent({
ColorQuestionWidget: resultMap.cmsContent.ColorQuestionWidget, ColorQuestionWidget: resultMap.cmsContent.ColorQuestionWidget,
FeatureQuestionWidget: resultMap.cmsContent.FeatureQuestionWidget, FeatureQuestionWidget: resultMap.cmsContent.FeatureQuestionWidget,
}) })
); );
}); });
},
data() {
return {
selectedGlassParts: {},
alertWidgetData: Object,
alreadyPopulatedPartsData: [],
};
},
computed: {
isForwardActionDisabled() {
return (
this.selectedGlassPartNumbers.length !== this.PartsFromApi.partsOrQuestions.length
);
}, },
data() { selectedGlassPartNumbers() {
return { // Compile all selected parts from the page.
selectedGlassParts: {}, const numberArray = [];
alertWidgetData: Object, for (let glassPart of Object.values(this.selectedGlassParts)) {
alreadyPopulatedPartsData: [], if (glassPart?.partNumber) {
}; numberArray.push(glassPart.partNumber);
}
}
return numberArray;
}, },
computed: { PartsOrQuestions() {
isForwardActionDisabled() { const partsData = this.PartsFromApi;
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)) {
if (glassPart?.partNumber) {
numberArray.push(glassPart.partNumber);
}
}
return numberArray;
},
PartsOrQuestions() {
const partsData = this.PartsFromApi;
// Map API result data, to vehicle-parts data structure // Map API result data, to vehicle-parts data structure
const mappedData = partsData.partsOrQuestions.map((g) => { const mappedData = partsData.partsOrQuestions.map((g) => {
return { return {
glassName: g.glassName, glassName: g.glassName,
glassLocation: g.glassLocation, glassLocation: g.glassLocation,
colorAnswers: g.parts?.reduce((arr, p) => { colorAnswers: g.parts?.reduce((arr, p) => {
arr.push({ arr.push({
ColorAnswerText: p.color, ColorAnswerText: p.color,
FeatureAnswers: [ FeatureAnswers: [
{ {
FeatureAnswerText: FeatureAnswerText:
p.description === "" ? p.color : p.description, p.description === "" ? p.color : p.description,
PartNumber: p.partNumber, PartNumber: p.partNumber,
}, },
], ],
});
return arr;
}, []),
};
});
return mappedData;
},
PartsFromApi() {
return this.mainStore.pageData(issPageValues.VEHICLE_PARTS);
},
RefPrefix() {
return "partQuestion";
},
},
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
);
},
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)) {
const currentPart = this.PartsFromApi.partsOrQuestions[key].parts[partKey];
const isMatched = this.selectedGlassPartNumbers.some(
(p) => p === currentPart.partNumber
);
if (isMatched) {
matchedParts.push({
glassLocation: value.glassLocation,
glassName: value.glassName,
parts: [currentPart],
});
}
}
}
// If no parts could be matched, throw an error (isForwardActionDisabled is based off of matchedParts)
if (this.isForwardActionDisabled) {
this.$refs.siteFooter.removeLoader();
throw new Error("Could not match any parts to the selected parts");
}
await this.mainStore.resetMoldingAndCapabilityQuestionAnswersIfNeeded(matchedParts);
this.navigateForward(matchedParts, null);
},
LoadInitialPartsData() {
const partsData = this.PartsFromApi;
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;
g.parts.forEach((p) => {
if (p.partNumber === partNumber) {
this.selectedGlassParts[g.glassLocation + "-" + g.glassName] = p;
}
}); });
return arr;
}, []),
};
});
return mappedData;
},
PartsFromApi() {
return this.mainStore.pageData(issPageValues.VEHICLE_PARTS);
},
RefPrefix() {
return "partQuestion";
},
},
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
);
},
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)) {
const currentPart = this.PartsFromApi.partsOrQuestions[key].parts[partKey];
const isMatched = this.selectedGlassPartNumbers.some(
(p) => p === currentPart.partNumber
);
if (isMatched) {
matchedParts.push({
glassLocation: value.glassLocation,
glassName: value.glassName,
parts: [currentPart],
});
}
}
}
// If no parts could be matched, throw an error (isForwardActionDisabled is based off of matchedParts)
if (this.isForwardActionDisabled) {
this.$refs.siteFooter.removeLoader();
throw new Error("Could not match any parts to the selected parts");
}
await this.mainStore.resetMoldingAndCapabilityQuestionAnswersIfNeeded(matchedParts);
this.navigateForward(matchedParts, null);
},
LoadInitialPartsData() {
const partsData = this.PartsFromApi;
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;
g.parts.forEach((p) => {
if (p.partNumber === partNumber) {
this.selectedGlassParts[g.glassLocation + "-" + g.glassName] = p;
}
}); });
}); });
}, });
},
mounted() {
this.LoadInitialPartsData();
},
components: {
Form,
glassPartQuestion,
siteHeader,
vehicleBanner,
siteSubHeader,
siteFooter,
alert,
}, },
},
mounted() {
this.LoadInitialPartsData();
},
components: {
Form,
glassPartQuestion,
siteHeader,
vehicleBanner,
siteSubHeader,
siteFooter,
alert,
},
}; };
</script> </script>
<style lang="scss"> <style lang="scss" scoped>
.overflow-scroll { .fade-on-route-transition {
height: calc(100% - 180px); margin-bottom: 100px;
overflow-x: hidden !important; }
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
} }
#vehicle-parts-alert { #vehicle-parts-alert {

View file

@ -1,22 +1,20 @@
<template> <template>
<div class="page-container-grouped-styles"> <div class="page-container-grouped-styles position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition position-relative">
<div class="select-car"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="select-car-form rounded text-center"> <div class="select-car">
<vehicleBanner cmsWidgetName="VehicleBannerWidget" class="mb-3" displayGenericVehicleImage /> <div class="container-fluid pb-2">
<siteSubHeader <div class="row">
cmsWidgetName="SiteSubHeaderWidget" <div class="col">
:hasBackButton="true" <div class="select-car-form rounded text-center">
:backButtonAccessibleText="backButtonAccessibleText" <vehicleBanner cmsWidgetName="VehicleBannerWidget" class="mb-3" displayGenericVehicleImage />
@click-event="backButtonAction" /> <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" :hasBackButton="true" :backButtonAccessibleText="backButtonAccessibleText" @click-event="backButtonAction" />
<div class="fade-on-route-transition"> <styleQuestion v-model="selectedStyle" ref="styleQuestion" cmsWidgetName="VehicleStyleQuestion" class="px-4" />
<styleQuestion <siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter" @back-clicked="backButtonAction" :isForwardButtonHidden="shouldHideForwardButton" />
v-model="selectedStyle" </div>
ref="styleQuestion" </div>
cmsWidgetName="VehicleStyleQuestion" /> </div>
</div> </div>
<siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter"
@back-clicked="backButtonAction" :isForwardButtonHidden="shouldHideForwardButton" />
</div> </div>
</div> </div>
</div> </div>
@ -124,3 +122,21 @@ export default {
} }
}; };
</script> </script>
<style lang="scss" scoped>
.container-fluid {
margin-bottom: 80px;
}
.fade-on-route-transition {
margin-bottom: 80px;
}
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
}
</style>

View file

@ -1,101 +1,116 @@
<template> <template>
<div class="page-container-grouped-styles"> <div class="page-container-grouped-styles position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <div class="fade-on-route-transition position-relative">
<div class="select-car"> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="select-car-form rounded text-center"> <div class="select-car">
<vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="true" class="mb-3" /> <div class="container-fluid pb-2">
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget" /> <div class="row">
<div class="fade-on-route-transition"> <div class="col">
<yearQuestion <div class="select-car-form rounded text-center">
class="fade-on-route-transition" <vehicleBanner cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="true" class="mb-3" />
v-model="selectedYear" <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
ref="yearQuestion" <yearQuestion class="px-4" v-model="selectedYear" ref="yearQuestion" cmsWidgetName="VehicleYearQuestion" />
cmsWidgetName="VehicleYearQuestion" <siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter" @back-clicked="backButtonAction" :isForwardButtonHidden="shouldHideForwardButton" />
/> </div>
</div> </div>
<siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter" </div>
@back-clicked="backButtonAction" :isForwardButtonHidden="shouldHideForwardButton" /> </div>
</div>
</div> </div>
</div>
</div> </div>
</template> </template>
<script> <script>
// Components // Components
import yearQuestion from "@/layouts/vehicle-year/year-question/year-question"; import yearQuestion from "@/layouts/vehicle-year/year-question/year-question";
import siteHeader from "@/iss-components/site-header/site-header"; import siteHeader from "@/iss-components/site-header/site-header";
import siteFooter from "@/iss-components/site-footer/site-footer"; import siteFooter from "@/iss-components/site-footer/site-footer";
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header"; import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header";
import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner"; import vehicleBanner from "@/iss-components/vehicle-banner/vehicle-banner";
// Supporting files // Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper"; import { settleAllPromises } from "@/helpers/layout-helper";
export default { export default {
name: "vehicle-year", name: "vehicle-year",
data() { data() {
return { return {
selectedYear: null, selectedYear: null,
shouldHideForwardButton: true shouldHideForwardButton: true
}; };
}, },
computed: {}, computed: {},
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
const yearQuestionInitialDataPromise = yearQuestion.methods.loadInitialData(); const yearQuestionInitialDataPromise = yearQuestion.methods.loadInitialData();
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{ {
resultKey: "cmsContent", resultKey: "cmsContent",
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
{ {
resultKey: "yearQuestionInitialData", resultKey: "yearQuestionInitialData",
promise: yearQuestionInitialDataPromise, promise: yearQuestionInitialDataPromise,
}, },
]; ];
let resultMap = await settleAllPromises(promiseResultMap); let resultMap = await settleAllPromises(promiseResultMap);
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.$refs.yearQuestion.initializeComponent( vm.$refs.yearQuestion.initializeComponent(
resultMap.yearQuestionInitialData resultMap.yearQuestionInitialData
); );
}); });
}, },
watch: { watch: {
selectedYear(year) { selectedYear(year) {
const parsedYear = parseInt(year); const parsedYear = parseInt(year);
this.mainStore.updateVehicleYear( parsedYear ); this.mainStore.updateVehicleYear( parsedYear );
this.$router.navigate( this.$router.navigate(
this.navigationScenarios.SELECTED_YEAR, this.navigationScenarios.SELECTED_YEAR,
this.$route this.$route
); );
}, },
}, },
methods: { methods: {
arePagePrerequisitesValid() { arePagePrerequisitesValid() {
return true; return true;
}, },
backButtonAction() { backButtonAction() {
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route); this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
}, },
}, },
components: { components: {
yearQuestion, yearQuestion,
siteHeader, siteHeader,
siteSubHeader, siteSubHeader,
vehicleBanner, vehicleBanner,
siteFooter siteFooter
}, },
}; };
</script> </script>
<style lang="scss" scoped>
.fade-on-route-transition {
margin-bottom: 80px;
}
.page-container-grouped-styles {
overflow: auto;
}
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
}
</style>

View file

@ -1,47 +1,27 @@
<template> <template>
<Form <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
@submit="onSubmit" <div class="page-container-grouped-styles">
@invalidSubmit="onInvalidSubmit" <div class="fade-on-route-transition position-relative">
v-slot="{ meta }" <siteHeader cmsWidgetName="SiteHeaderWidget" />
> <div class="select-car">
<div class="page-container-grouped-styles "> <div class="container-fluid pb-2">
<siteHeader <div class="row px-3">
cmsWidgetName="SiteHeaderWidget" <div class="col">
/> <div class="select-car-form rounded">
<div class="px-4 overflow-scroll "> <vehicleBanner class="mb-3" cmsWidgetName="VehicleBannerWidget" :displayGenericVehicleImage="false" />
<div class="fade-on-route-transition sub-container px-2"> <siteSubHeader cmsWidgetName="SiteSubHeaderWidget" />
<vehicleBanner <vinLookupAlerts class="mt-5" :activeAlertType="activeVehicleLookupAlertType" />
class="mb-3" <vinQuestion v-model="vin" :mask="vinMask" :isDisabled="vinPopulatedOnPageLoad" textPosition="left" />
cmsWidgetName="VehicleBannerWidget" <vinLocationInformation />
:displayGenericVehicleImage="false" <siteFooter cmsWidgetName="SiteFooterWidget" :isForwardActionDisabled="!meta.valid" @backClicked="backButtonAction" @forwardClicked="forwardButtonAction" ref="siteFooter" />
/> </div>
<siteSubHeader </div>
cmsWidgetName="SiteSubHeaderWidget" </div>
/> </div>
<vinLookupAlerts </div>
class="mt-5"
:activeAlertType="activeVehicleLookupAlertType"
/>
<vinQuestion
v-model="vin"
:mask="vinMask"
:isDisabled="vinPopulatedOnPageLoad"
/>
<vinLocationInformation />
<siteFooter
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!meta.valid"
@backClicked="backButtonAction"
@forwardClicked="forwardButtonAction"
ref="siteFooter"
/>
</div> </div>
</div> </div>
</div> </Form>
</Form>
</template> </template>
<script> <script>
// Import Supporting Files // Import Supporting Files
@ -81,25 +61,25 @@ export default {
setup() { setup() {
const mainStore = useMainStore(); const mainStore = useMainStore();
return { mainStore }; return { mainStore };
}, },
data() { data() {
return { return {
activeVehicleLookupAlertType: null, activeVehicleLookupAlertType: null,
needToLookupVehicle: true, needToLookupVehicle: true,
vehicleFromLookup: null, vehicleFromLookup: null,
vin: this.getVinFromStore(), vin: this.getVinFromStore(),
forwardButtonCarStyle:"", forwardButtonCarStyle:"",
vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0, vinPopulatedOnPageLoad: this.getVinFromStore()?.length > 0,
}; };
}, },
provide() { provide() {
return { return {
vehicleFromLookup: computed(() => this.vehicleFromLookup), vehicleFromLookup: computed(() => this.vehicleFromLookup),
}; };
}, },
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
@ -111,51 +91,51 @@ export default {
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
}); });
},
computed: {
isCarIdDifferentFromTheStore() {
return (
this.vehicleFromLookup !== null
&& this.vehicleFromLookup.carId !== this.mainStore.vehicle.carId
);
}, },
isTwoIdenticalYMMVehicleFound(){ computed: {
const vinYmmFound = `${this.vehicleFromLookup.year} ${this.vehicleFromLookup.make} ${this.vehicleFromLookup.model}`; isCarIdDifferentFromTheStore() {
const vinYmmExpected = `${this.mainStore.order.vehicle.year} ${this.mainStore.order.vehicle.make} ${this.mainStore.order.vehicle.model}`; return (
return(vinYmmFound.toLowerCase()==vinYmmExpected.toLowerCase()); this.vehicleFromLookup !== null
&& this.vehicleFromLookup.carId !== this.mainStore.vehicle.carId
);
},
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());
},
vinMask() {
if (this.vinPopulatedOnPageLoad) {
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";
}
},
}, },
vinMask() { methods: {
if (this.vinPopulatedOnPageLoad) { arePagePrerequisiteValid() {
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.PERFECT_MATCH; return true;
this.needToLookupVehicle = false; },
const lastSixChars = this.vin.substring(11, this.vin.length); getVinFromStore() {
return `!X!X!X!X!X!X!X!X!X!X!X${lastSixChars}`; return this.mainStore.vehicle.vin;
} else { },
return "XXXXXXXXXXXXXXXXX"; backButtonAction() {
} /**
}, * this.navigationScenarios comes from base-mixin
}, */
methods: { this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
arePagePrerequisiteValid() { },
return true; // NOTE: If form is not valid, this method is not called when 'Continue' button is clicked
}, async forwardButtonAction() {
getVinFromStore() { this.resetActiveAlert();
return this.mainStore.vehicle.vin; // Temp solution to reset the 'disabled' style on the Continue button
}, this.$refs.siteFooter.enableForwardAction();
backButtonAction() {
/**
* this.navigationScenarios comes from base-mixin
*/
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
// NOTE: If form is not valid, this method is not called when 'Continue' button is clicked
async forwardButtonAction() {
this.resetActiveAlert();
// Temp solution to reset the 'disabled' style on the Continue button
this.$refs.siteFooter.enableForwardAction();
if (this.needToLookupVehicle) { if (this.needToLookupVehicle) {
const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin); const vehicleLookupResponse = await this.lookupVehicleByVin(this.vin);
@ -175,18 +155,18 @@ export default {
this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, { vin: this.vin }); this.vehicleFromLookup = Object.assign(vehicleLookupResponse.data, { vin: this.vin });
} }
if (this.needToLookupVehicle && this.isCarIdDifferentFromTheStore) { if (this.needToLookupVehicle && this.isCarIdDifferentFromTheStore) {
if(this.isTwoIdenticalYMMVehicleFound){ if(this.isTwoIdenticalYMMVehicleFound){
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.TWO_IDENTICAL_YMM_MATCHED; this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.TWO_IDENTICAL_YMM_MATCHED;
this.forwardButtonCarStyle = this.vehicleFromLookup.style; this.forwardButtonCarStyle = this.vehicleFromLookup.style;
} }
else{ else{
this.activeVehicleLookupAlertType = vehicleLookupAlertTypes.NOT_MATCHED; 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.updateButtonText(`Continue with ${vehicleYearMakeModelStyle}`);
this.$refs.siteFooter.removeLoader(); this.$refs.siteFooter.removeLoader();
this.needToLookupVehicle = false; this.needToLookupVehicle = false;
@ -213,18 +193,18 @@ export default {
return; return;
} }
// save vehicle to store if it hasn't already been saved // save vehicle to store if it hasn't already been saved
if (!this.vinPopulatedOnPageLoad) { if (!this.vinPopulatedOnPageLoad) {
this.mainStore.updateVehicle(this.vehicleFromLookup); this.mainStore.updateVehicle(this.vehicleFromLookup);
} }
const partsOrQuestionsResponse = await this.getPartsOrQuestions(); const partsOrQuestionsResponse = await this.getPartsOrQuestions();
if (partsOrQuestionsResponse.error) { if (partsOrQuestionsResponse.error) {
// To Do: Need requirement on what to do here // To Do: Need requirement on what to do here
console.error('Error on retrieving PartsOrQuestions'); console.error('Error on retrieving PartsOrQuestions');
this.$refs.siteFooter.removeLoader(); this.$refs.siteFooter.removeLoader();
return; return;
} }
// Comes from vehicleQuestionsMixin.navigateForward() // Comes from vehicleQuestionsMixin.navigateForward()
await this.navigateForward(partsOrQuestionsResponse.data.partsOrQuestions, this); await this.navigateForward(partsOrQuestionsResponse.data.partsOrQuestions, this);
@ -274,11 +254,18 @@ export default {
}, },
}; };
</script> </script>
<style>
.overflow-scroll { <style lang="scss" scoped>
height: calc(100% - 180px); .fade-on-route-transition {
overflow-X: hidden !important; margin-bottom: 100px;
}
.page-container-grouped-styles {
overflow: auto;
} }
.modal-open {
.page-container-grouped-styles {
overflow: hidden;
}
}
</style> </style>

View file

@ -1,116 +1,115 @@
<template> <template>
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" > <Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
<div class="page-container-grouped-styles welcome">
<div class="page-container-grouped-styles welcome"> <div class="fade-on-route-transition position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget"/> <siteHeader cmsWidgetName="SiteHeaderWidget"/>
<div class="fade-on-route-transition overflow-scroll container"> <siteSubHeader cmsWidgetName="SiteSubHeaderWidget"/>
<div class="container-fluid pb-2">
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget"/> <div class="row mt-4 px-3">
<div class="row mt-4 px-3"> <div class="col">
<div class="col"> <textboxQuestion
<textboxQuestion inputId="policyNumberField"
inputId="policyNumberField" cmsWidgetName="PolicyNumberQuestion"
cmsWidgetName="PolicyNumberQuestion" v-model="welcomePageModel.policyNumber"
v-model="welcomePageModel.policyNumber" isRequired
isRequired ref="policyNumber"
ref="policyNumber" disableAutoFill
disableAutoFill validationRules="policy-number-required" />
validationRules="policy-number-required" /> </div>
</div> </div>
</div> <div class="row mt-4 px-3">
<div class="row mt-4 px-3"> <div class="col">
<div class="col"> <textboxQuestion
<textboxQuestion type="date"
type="date" cmsWidgetName="DateOfLossQuestion"
cmsWidgetName="DateOfLossQuestion" v-model="welcomePageModel.dateOfLoss"
v-model="welcomePageModel.dateOfLoss" inputId="dateOfLossField"
inputId="dateOfLossField" isRequired
isRequired ref="dateOfLoss"
ref="dateOfLoss" disableAutoFill
disableAutoFill :max="new Date().toJSON().slice(0,10)"
:max="new Date().toJSON().slice(0,10)" :min="'1972-12-01'"
:min="'1972-12-01'" validationRules="loss-date-required"
validationRules="loss-date-required" />
/> </div>
</div> </div>
</div> <div class="row px-5">
<div class="row px-5"> <div class="col px-0">
<div class="col px-0"> <textBlock cmsWidgetName="DamageDateEstimateWidget" typeStyle="small" class="mt-2" />
<textBlock cmsWidgetName="DamageDateEstimateWidget" typeStyle="small" class="mt-2" /> </div>
</div> </div>
</div> <div class="row mt-4 px-3">
<div class="row mt-4 px-3"> <div class="col">
<div class="col"> <dropdownQuestion
<dropdownQuestion cmsWidgetName="DamageCauseQuestion"
cmsWidgetName="DamageCauseQuestion" v-model="welcomePageModel.damageCause"
v-model="welcomePageModel.damageCause" ref="damageCause"
ref="damageCause" inputId="damageCauseQuestionField"
inputId="damageCauseQuestionField" :options="DamageCauseOptions"
:options="DamageCauseOptions" disableAutoFill
disableAutoFill validationRules="damage-option-required"
validationRules="damage-option-required" placeHolderText="Select an option"
placeHolderText="Select an option" id="welcomeDropdown"
id="welcomeDropdown" />
/> </div>
</div> </div>
</div> <div class="row mt-4 px-3">
<div class="row mt-4 px-3"> <div class="col">
<div class="col"> <textboxQuestion
<textboxQuestion inputId="phoneNumberField"
inputId="phoneNumberField" cmsWidgetName="PhoneNumberQuestion"
cmsWidgetName="PhoneNumberQuestion" v-model="welcomePageModel.phoneNumber"
v-model="welcomePageModel.phoneNumber" validationRules="phone-number-required|phone-number-format"
validationRules="phone-number-required|phone-number-format" isRequired
isRequired ref="phoneNumber"
ref="phoneNumber" mask="###-###-####"
mask="###-###-####" disableAutoFill />
disableAutoFill /> </div>
</div> </div>
</div> <div class="row mt-4 px-3">
<div class="row mt-4 px-3"> <div class="col">
<div class="col"> <textboxQuestion
<textboxQuestion inputId="emailField"
inputId="emailField" cmsWidgetName="EmailAddressQuestion"
cmsWidgetName="EmailAddressQuestion" v-model="welcomePageModel.email"
v-model="welcomePageModel.email" ref="email"
ref="email" validationRules="email-address-required|email-address-format"
validationRules="email-address-required|email-address-format" isRequired
isRequired disableAutoFill />
disableAutoFill /> </div>
</div> </div>
</div> <div class="row mt-4 px-3">
<div class="row mt-4 px-3"> <div class="col">
<div class="col"> <textboxQuestion
<textboxQuestion inputId="damageCityField"
inputId="damageCityField" cmsWidgetName="DamageCityQuestion"
cmsWidgetName="DamageCityQuestion" v-model="welcomePageModel.damageCity"
v-model="welcomePageModel.damageCity" isRequired
isRequired ref="damageCity"
ref="damageCity" disableAutoFill
disableAutoFill v-if="this.displayDamageCityQuestion"
v-if="this.displayDamageCityQuestion" validationRules="loss-city-required" />
validationRules="loss-city-required" /> </div>
</div> </div>
</div> <div class="row mt-4 px-3">
<div class="row mt-4 px-3"> <div class="col">
<div class="col"> <dropdownQuestion
<dropdownQuestion cmsWidgetName="DamageStateQuestion"
cmsWidgetName="DamageStateQuestion" v-model="welcomePageModel.damageState"
v-model="welcomePageModel.damageState" ref="state"
ref="state" inputId="8fdf9dc2e13e430eb57529499dceb3eb"
inputId="8fdf9dc2e13e430eb57529499dceb3eb" :options="stateOptions"
:options="stateOptions" validationRules="loss-state-required"
validationRules="loss-state-required" isRequired
isRequired disableAutoFill
disableAutoFill v-if="this.displayDamageStateQuestion"
v-if="this.displayDamageStateQuestion" placeHolderText="Select an option"
placeHolderText="Select an option" id="welcomeDropdown"
id="welcomeDropdown" />
/> </div>
</div> </div>
</div> <div class="row mt-4">
<div class="row mt-4"> <buttonQuestion
<buttonQuestion
class="px-0" class="px-0"
cmsWidgetName="GlassOnlyQuestion" cmsWidgetName="GlassOnlyQuestion"
v-model="welcomePageModel.isDamageGlassOnly" v-model="welcomePageModel.isDamageGlassOnly"
@ -124,234 +123,241 @@
ref="glassOnlyDamage" ref="glassOnlyDamage"
v-if="this.displayGlassOnlyQuestion" v-if="this.displayGlassOnlyQuestion"
disableAutoFill/> disableAutoFill/>
</div> </div>
<div class="row mt-4 position-sticky top-100" id="welcomeFooter"> <div class="row mt-4 position-sticky top-100" id="welcomeFooter">
<div class="col"> <div class="col">
<site-footer <site-footer
cmsWidgetName="SiteFooterWidget" cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!meta.valid" :isForwardActionDisabled="!meta.valid"
@back-clicked="backButtonAction" @back-clicked="backButtonAction"
@ForwardClicked="forwardButtonAction" /> @ForwardClicked="forwardButtonAction" />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </Form>
</Form>
</template> </template>
<script> <script>
// Components // Components
import siteHeader from '@/iss-components/site-header/site-header'; import siteHeader from '@/iss-components/site-header/site-header';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header'; import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header';
import siteFooter from "@/iss-components/site-footer/site-footer"; import siteFooter from "@/iss-components/site-footer/site-footer";
import textboxQuestion from "@/digital-components/textbox-question/textbox-question"; import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
import buttonQuestion from "@/digital-components/button-question/button-question"; import buttonQuestion from "@/digital-components/button-question/button-question";
import dropdownQuestion from "@/digital-components/dropdown-question/dropdown-question"; import dropdownQuestion from "@/digital-components/dropdown-question/dropdown-question";
import textBlock from "@/digital-components/text-block/text-block"; import textBlock from "@/digital-components/text-block/text-block";
// Supporting files // Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper"; import { settleAllPromises } from "@/helpers/layout-helper";
import { Form, defineRule } from "vee-validate"; import { Form, defineRule } from "vee-validate";
import { required, regex } from "@/helpers/validation-rules"; import { required, regex } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages"; import { errorMessages } from "@/constants/error-messages";
import BaseFormMixin from '@/mixins/base-form-mixin.js'; import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { useMainStore } from '@/store'; import { useMainStore } from '@/store';
//define validation rules //define validation rules
defineRule("loss-date-required", required(errorMessages.LOSS_DATE_REQUIRED)); defineRule("loss-date-required", required(errorMessages.LOSS_DATE_REQUIRED));
defineRule("loss-cause-required", required(errorMessages.LOSS_CAUSE_REQUIRED)); defineRule("loss-cause-required", required(errorMessages.LOSS_CAUSE_REQUIRED));
defineRule("policy-number-required", required(errorMessages.POLICY_NUMBER_REQUIRED)); defineRule("policy-number-required", required(errorMessages.POLICY_NUMBER_REQUIRED));
defineRule("loss-date-required", required(errorMessages.LOSS_DATE_REQUIRED)); defineRule("loss-date-required", required(errorMessages.LOSS_DATE_REQUIRED));
defineRule("loss-state-required", required(errorMessages.LOSS_STATE_REQUIRED)); defineRule("loss-state-required", required(errorMessages.LOSS_STATE_REQUIRED));
defineRule("loss-city-required", required(errorMessages.LOSS_CITY_REQUIRED)); defineRule("loss-city-required", required(errorMessages.LOSS_CITY_REQUIRED));
defineRule("phone-number-required", required(errorMessages.PHONE_NUMBER_FORMAT)); defineRule("phone-number-required", required(errorMessages.PHONE_NUMBER_FORMAT));
defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED)); defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
defineRule("damage-option-required", required(errorMessages.DAMAGE_OPTION_REQUIRED)); defineRule("damage-option-required", required(errorMessages.DAMAGE_OPTION_REQUIRED));
defineRule("email-address-format", defineRule("email-address-format",
regex( regex(
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,})$/, /^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,})$/,
errorMessages.EMAIL_ADDRESS_FORMAT errorMessages.EMAIL_ADDRESS_FORMAT
) )
); );
defineRule("phone-number-format", defineRule("phone-number-format",
regex( regex(
/^(\([0-9]{3}\)|[0-9]{3}) *[-.]? *[0-9]{3} *[-.]? *[0-9]{4}$/, /^(\([0-9]{3}\)|[0-9]{3}) *[-.]? *[0-9]{3} *[-.]? *[0-9]{4}$/,
errorMessages.PHONE_NUMBER_FORMAT errorMessages.PHONE_NUMBER_FORMAT
) )
); );
export default { export default {
name: "welcome-page", name: "welcome-page",
mixins: [BaseFormMixin], mixins: [BaseFormMixin],
data() { data() {
return { return {
welcomePageModel: this.getWelcomePageModelFromStore() welcomePageModel: this.getWelcomePageModelFromStore()
}; };
}, },
setup() { setup() {
const mainStore = useMainStore(); const mainStore = useMainStore();
// Set order account number from the issConfig. // Set order account number from the issConfig.
mainStore.order.accountNumber = mainStore.issConfig.accountNumber; mainStore.order.accountNumber = mainStore.issConfig.accountNumber;
return { mainStore }; return { mainStore };
}, },
async beforeRouteEnter(to, from, next) async beforeRouteEnter(to, from, next)
{ {
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{ {
resultKey: "cmsContent", resultKey: "cmsContent",
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
]; ];
//use resultMap to populate layout content. //use resultMap to populate layout content.
let resultMap = await settleAllPromises(promiseResultMap); let resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
});
},
methods:
{
async forwardButtonAction() {
this.mainStore.updatePolicyData(this.welcomePageModel);
return this.navigateForward();
},
navigateForward() { next((vm) => {
this.$router.navigate( vm.setCmsContent(resultMap.cmsContent);
this.navigationScenarios.CLICKED_FORWARD_WELCOME_PAGE, });
this.$route },
); methods:
}, {
getWelcomePageModelFromStore() { async forwardButtonAction() {
return { this.mainStore.updatePolicyData(this.welcomePageModel);
policyNumber : this.mainStore.order.policy.policyNumber, return this.navigateForward();
dateOfLoss : this.mainStore.order.policy.dateOfLoss,
damageCause : this.mainStore.order.policy.damageCause,
damageState : this.mainStore.order.policy.damageState,
damageCity : this.mainStore.order.policy.damageCity,
isDamageGlassOnly : this.mainStore.order.policy.isDamageGlassOnly,
phoneNumber : this.mainStore.order.customer.phoneNumber,
email : this.mainStore.order.customer.emailAddress,
}
},
}, },
computed:{
DamageCauseOptions() { navigateForward() {
const damageCauseAnswers = this.getCmsContent("DamageCauseQuestion", "Answers"); this.$router.navigate(
const damageCauseAnswersObj ={}; this.navigationScenarios.CLICKED_FORWARD_WELCOME_PAGE,
if(damageCauseAnswers) this.$route
{ );
for (let answer of Object.values(damageCauseAnswers)) { },
if (answer?.Name) { getWelcomePageModelFromStore() {
damageCauseAnswersObj[answer.Name] = answer.Name; return {
} policyNumber : this.mainStore.order.policy.policyNumber,
} dateOfLoss : this.mainStore.order.policy.dateOfLoss,
} damageCause : this.mainStore.order.policy.damageCause,
return damageCauseAnswersObj; damageState : this.mainStore.order.policy.damageState,
}, damageCity : this.mainStore.order.policy.damageCity,
DamageGlassOnlyOptions() isDamageGlassOnly : this.mainStore.order.policy.isDamageGlassOnly,
{ phoneNumber : this.mainStore.order.customer.phoneNumber,
return this.getCmsContent("GlassOnlyQuestion", "Answers"); email : this.mainStore.order.customer.emailAddress,
},
DamageGlassOnlyQuestion()
{
return this.getCmsContent("GlassOnlyQuestion", "QuestionText");
},
stateOptions: {
get: function () {
return {
AL: "Alabama",
AK: "Alaska",
AZ: "Arizona",
AR: "Arkansas",
CA: "California",
CO: "Colorado",
CT: "Connecticut",
DE: "Delaware",
DC: "District Of Columbia",
FL: "Florida",
GA: "Georgia",
HI: "Hawaii",
ID: "Idaho",
IL: "Illinois",
IN: "Indiana",
IA: "Iowa",
KS: "Kansas",
KY: "Kentucky",
LA: "Louisiana",
ME: "Maine",
MD: "Maryland",
MA: "Massachusetts",
MI: "Michigan",
MN: "Minnesota",
MS: "Mississippi",
MO: "Missouri",
MT: "Montana",
NE: "Nebraska",
NV: "Nevada",
NH: "New Hampshire",
NJ: "New Jersey",
NM: "New Mexico",
NY: "New York",
NC: "North Carolina",
ND: "North Dakota",
OH: "Ohio",
OK: "Oklahoma",
OR: "Oregon",
PA: "Pennsylvania",
RI: "Rhode Island",
SC: "South Carolina",
SD: "South Dakota",
TN: "Tennessee",
TX: "Texas",
UT: "Utah",
VT: "Vermont",
VA: "Virginia",
WA: "Washington",
WV: "West Virginia",
WI: "Wisconsin",
WY: "Wyoming",
};
},
},
displayDamageCityQuestion(){
return !!this.getCmsContent("DamageCityQuestion","QuestionText");
},
displayDamageStateQuestion(){
return !!this.getCmsContent("DamageStateQuestion","QuestionText");
},
displayGlassOnlyQuestion(){
return !!this.getCmsContent("GlassOnlyQuestion","QuestionText");
} }
}, },
components: { },
siteHeader, computed:{
siteSubHeader, DamageCauseOptions() {
buttonQuestion, const damageCauseAnswers = this.getCmsContent("DamageCauseQuestion", "Answers");
textboxQuestion, const damageCauseAnswersObj ={};
dropdownQuestion, if(damageCauseAnswers)
siteFooter, {
textBlock, for (let answer of Object.values(damageCauseAnswers)) {
Form, if (answer?.Name) {
damageCauseAnswersObj[answer.Name] = answer.Name;
}
}
}
return damageCauseAnswersObj;
}, },
} DamageGlassOnlyOptions()
{
return this.getCmsContent("GlassOnlyQuestion", "Answers");
},
DamageGlassOnlyQuestion()
{
return this.getCmsContent("GlassOnlyQuestion", "QuestionText");
},
stateOptions: {
get: function () {
return {
AL: "Alabama",
AK: "Alaska",
AZ: "Arizona",
AR: "Arkansas",
CA: "California",
CO: "Colorado",
CT: "Connecticut",
DE: "Delaware",
DC: "District Of Columbia",
FL: "Florida",
GA: "Georgia",
HI: "Hawaii",
ID: "Idaho",
IL: "Illinois",
IN: "Indiana",
IA: "Iowa",
KS: "Kansas",
KY: "Kentucky",
LA: "Louisiana",
ME: "Maine",
MD: "Maryland",
MA: "Massachusetts",
MI: "Michigan",
MN: "Minnesota",
MS: "Mississippi",
MO: "Missouri",
MT: "Montana",
NE: "Nebraska",
NV: "Nevada",
NH: "New Hampshire",
NJ: "New Jersey",
NM: "New Mexico",
NY: "New York",
NC: "North Carolina",
ND: "North Dakota",
OH: "Ohio",
OK: "Oklahoma",
OR: "Oregon",
PA: "Pennsylvania",
RI: "Rhode Island",
SC: "South Carolina",
SD: "South Dakota",
TN: "Tennessee",
TX: "Texas",
UT: "Utah",
VT: "Vermont",
VA: "Virginia",
WA: "Washington",
WV: "West Virginia",
WI: "Wisconsin",
WY: "Wyoming",
};
},
},
displayDamageCityQuestion(){
return !!this.getCmsContent("DamageCityQuestion","QuestionText");
},
displayDamageStateQuestion(){
return !!this.getCmsContent("DamageStateQuestion","QuestionText");
},
displayGlassOnlyQuestion(){
return !!this.getCmsContent("GlassOnlyQuestion","QuestionText");
}
},
components: {
siteHeader,
siteSubHeader,
buttonQuestion,
textboxQuestion,
dropdownQuestion,
siteFooter,
textBlock,
Form,
},
}
</script> </script>
<style lang="scss"> <style lang="scss">
.overflow-scroll { .fade-on-route-transition {
height: calc(100% - 165px); height: calc(100% - 80px);
overflow-X: hidden !important; overflow: scroll;
}
.modal-open {
.fade-on-route-transition {
overflow: hidden;
}
} }
.my-2 .my-2
{ {

View file

@ -46,7 +46,7 @@ body {
} }
.page-container-grouped-styles { .page-container-grouped-styles {
@extend .container-fluid, .shadow, .rounded-3, .p-0, .position-relative, .make-tall; @extend .container-fluid, .shadow, .p-0, .position-relative, .make-tall;
} }
//Footer modal backdrop adjustments for positioning //Footer modal backdrop adjustments for positioning