More alert/error/etc updates
This commit is contained in:
parent
253044d502
commit
d6762e85a8
6 changed files with 119 additions and 57 deletions
|
|
@ -26,7 +26,7 @@ const errorMessages = Object.freeze({
|
|||
SERVICE_ZIP_REQUIRED: 'ZIP code is required',
|
||||
SERVICE_ZIP_FORMAT: 'Invalid ZIP, please enter a new ZIP (5 characters)',
|
||||
MOBILE_SERVICE_ZIP_FORMAT: 'Invalid ZIP code',
|
||||
NO_SERVICE_IN_ZIP: (zip) => `We're sorry, but we don't offer service in ${zip} at this time.`,
|
||||
NO_SERVICE_IN_AREA: (area) => `We're sorry, but we don't offer service in ${area} at this time.`,
|
||||
PROVIDER_REQUIRED: 'Please select a provider.',
|
||||
INVALID_ZIP: 'The ZIP you entered was invalid. Please enter a valid ZIP.',
|
||||
ZIP_CODE_NOT_SERVICED_FOR_VEHICLE: 'We do not currently offer glass service for your vehicle in this ZIP code. Please try another ZIP code.',
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
ref="buttonQuestion"
|
||||
v-model="selectedValues"
|
||||
customButtonQuestionId="appointmentTypeQuestion"
|
||||
:answers="answersFromCms"
|
||||
:answers="answersToDisplay"
|
||||
:groupName="groupName"
|
||||
:suppressError="suppressError"
|
||||
:validationRules="validationRules"
|
||||
|
|
@ -45,8 +45,15 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||
},
|
||||
answersFromCms() {
|
||||
const retCms = this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
return retCms;
|
||||
return this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
},
|
||||
answersToDisplay() {
|
||||
return this.answersFromCms
|
||||
? this.answersFromCms.filter((answer) => (
|
||||
(answer.Name === AppointmentTypeStrings.IN_SHOP)
|
||||
|| (answer.Name === AppointmentTypeStrings.MOBILE)
|
||||
))
|
||||
: [];
|
||||
},
|
||||
selectedValues: {
|
||||
get() {
|
||||
|
|
|
|||
|
|
@ -13,18 +13,6 @@
|
|||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="subheader" />
|
||||
<alert
|
||||
v-if="displayServiceableMobileOnly"
|
||||
ref="alertMobileOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMobileOnlyWidget"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayServiceableInshopOnly"
|
||||
ref="alertInshopOnly"
|
||||
cmsWidgetName="AlertInshopOnlyWidget"
|
||||
:isCollapsible="true"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayRecalibrationWarning"
|
||||
ref="alertRecalNoMobile"
|
||||
|
|
@ -32,13 +20,6 @@
|
|||
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||
alertClass="alert-warning"
|
||||
@text-link-clicked="openModalAction" />
|
||||
<alert
|
||||
v-if="displayNoShopsAlert"
|
||||
ref="alertNoShops"
|
||||
class="my-5"
|
||||
:isCollapsible="true"
|
||||
cmsWidgetName="AlertNoShopsWidget"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayBigTruckNoShops"
|
||||
ref="alertBigTruckNoShops"
|
||||
|
|
@ -47,10 +28,25 @@
|
|||
alertClass="alert-warning" />
|
||||
<div class="appointment-type">
|
||||
<div class="appointment-type-question-text d-flex">
|
||||
<span class="w-100">{{ appointmentQuestionText }}</span>
|
||||
<span class="w-100 recal-text" v-if="recalibrationRequired">{{ scheduleRecalText }}</span>
|
||||
<span class="w-100" v-if="!requiresInshopRecalibration">{{ appointmentQuestionText }}</span>
|
||||
</div>
|
||||
<alert
|
||||
v-if="displayServiceableInshopOnly"
|
||||
ref="alertInshopOnly"
|
||||
cmsWidgetName="AlertInshopOnlyWidget"
|
||||
:manualCopy="inShopOnlyCopy"
|
||||
:isCollapsible="true"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayServiceableMobileOnly"
|
||||
ref="alertMobileOnly"
|
||||
cmsWidgetName="AlertMobileOnlyWidget"
|
||||
:manualCopy="mobileOnlyCopy"
|
||||
:isCollapsible="true"
|
||||
alertClass="alert-warning" />
|
||||
<appointmentTypeQuestion
|
||||
v-if="showMobileOption"
|
||||
v-if="!requiresInshopRecalibration && isServiceableMobile"
|
||||
ref="appointmentTypeQuestion"
|
||||
v-model="selectedAppointmentType"
|
||||
groupName="appointmentTypeQuestion"
|
||||
|
|
@ -66,6 +62,12 @@
|
|||
modalWidgetName="ChangeLocationModalWidget"
|
||||
cmsWidgetName="ShopAddressWidget"
|
||||
@zip-updated="handleInShopZipUpdated" />
|
||||
<alert
|
||||
v-if="selectedProvider === null"
|
||||
ref="alertNoAvailableShops"
|
||||
cmsWidgetName="AlertNoAvailableShopsWidget"
|
||||
:isCollapsible="true"
|
||||
alertClass="alert-danger" />
|
||||
</div>
|
||||
<div
|
||||
v-if="isMobile">
|
||||
|
|
@ -105,6 +107,7 @@
|
|||
cmsWidgetName="MobileFeeDisclaimerWidget"
|
||||
typeStyle="disclaimer" />
|
||||
</div>
|
||||
<!-- INTEGRATION TODO: Put this right under the calendar -->
|
||||
<contentGroupModal
|
||||
:ref="RECAL_MODAL_REF_NAME"
|
||||
cssModalHeadlineClass="text-center"
|
||||
|
|
@ -136,6 +139,7 @@ import {
|
|||
getZipCodeData,
|
||||
getMobileZipCodeData
|
||||
} from '@/helpers/service-location-helper';
|
||||
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||
|
||||
// Import Component
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
|
|
@ -232,7 +236,6 @@ export default {
|
|||
city: this.getServiceCityFromStore(),
|
||||
state: this.getServiceStateFromStore(),
|
||||
zipCode: this.getServiceZipCodeFromStore(),
|
||||
isVehicleProtected: this.getIsVehicleProtectedFromStore(),
|
||||
isGlassServiceableInshop: null,
|
||||
isRecalibrationServiceableInshop: null,
|
||||
isGlassServiceableMobile: null,
|
||||
|
|
@ -245,7 +248,6 @@ export default {
|
|||
zipCodeCtu: null,
|
||||
mobileZipCode: '',
|
||||
mobileZipError: '',
|
||||
showMobileOption: false,
|
||||
militaryBaseWarningExpanded: false,
|
||||
RECAL_MODAL_REF_NAME,
|
||||
SITE_FOOTER_REF_NAME,
|
||||
|
|
@ -313,12 +315,11 @@ export default {
|
|||
displayServiceableInshopOnly() {
|
||||
return (
|
||||
!this.displayRecalibrationWarning
|
||||
&& this.isServiceableInshop
|
||||
&& !this.isServiceableMobile
|
||||
);
|
||||
},
|
||||
displayServiceableMobileOnly() {
|
||||
return this.isServiceableMobile && !this.isServiceableInshop;
|
||||
return this.isServiceableMobile && !this.isServiceableInshop && this.displayRecalibrationWarning;
|
||||
},
|
||||
displayMobileFeeDisclaimer() {
|
||||
return this.mainStore.isNoComp || this.mainStore.isITAC;
|
||||
|
|
@ -342,7 +343,27 @@ export default {
|
|||
return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||
},
|
||||
appointmentQuestionText() {
|
||||
return this.getCmsContent('AppointmentTypeQuestionWidget', widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT);
|
||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT);
|
||||
},
|
||||
scheduleRecalText() {
|
||||
if(this.requiresInshopRecalibration) {
|
||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2);
|
||||
} else {
|
||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT);
|
||||
}
|
||||
},
|
||||
inShopOnlyCopy() {
|
||||
let content = this.getCmsContent('AlertInshopOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||
content = content.replace('{custom:city}', toTitleCase(this.city));
|
||||
return content;
|
||||
},
|
||||
mobileOnlyCopy() {
|
||||
let content = this.getCmsContent('AlertMobileOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||
content = content.replace('{custom:city}', toTitleCase(this.city));
|
||||
return content;
|
||||
},
|
||||
recalibrationRequired() {
|
||||
return this.isRecalibrationServiceableMobile !== null;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -379,7 +400,6 @@ export default {
|
|||
zipCode: this.zipCode,
|
||||
zipCodeCtu: this.zipCodeCtu,
|
||||
appointmentType: this.selectedAppointmentType,
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
provider
|
||||
});
|
||||
|
||||
|
|
@ -413,9 +433,6 @@ export default {
|
|||
|| useMainStore().order.customer.address.zipCode
|
||||
);
|
||||
},
|
||||
getIsVehicleProtectedFromStore() {
|
||||
return useMainStore().order.serviceLocation.isVehicleProtected;
|
||||
},
|
||||
getSelectedAppointmentType() {
|
||||
return useMainStore().order.serviceLocation.appointmentType;
|
||||
},
|
||||
|
|
@ -435,14 +452,11 @@ export default {
|
|||
if (zipCodeData) {
|
||||
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
|
||||
this.zipCodeCtu = zipCodeData.zipCodeCtu;
|
||||
this.city = zipCodeData.city;
|
||||
}
|
||||
|
||||
if (serviceabilityDetails) {
|
||||
this.setServiceabilityDetails(serviceabilityDetails);
|
||||
this.showMobileOption = this.isServiceableMobile;
|
||||
if (!this.showMobileOption) {
|
||||
this.selectedAppointmentType = AppointmentTypeStrings.IN_SHOP;
|
||||
}
|
||||
}
|
||||
|
||||
if (mobileFeePart) {
|
||||
|
|
@ -464,6 +478,9 @@ export default {
|
|||
if(providers.shopProviders.length > 0 && !foundMatch) {
|
||||
this.selectedProvider = providers.shopProviders[0];
|
||||
}
|
||||
else {
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (glassFees) {
|
||||
|
|
@ -485,13 +502,6 @@ export default {
|
|||
setMobileProviderNumber(providerNumber) {
|
||||
this.mobileProviderNumber = providerNumber;
|
||||
},
|
||||
resetMobileLocation() {
|
||||
this.streetAddress = '';
|
||||
this.streetAddress2 = '';
|
||||
this.city = '';
|
||||
|
||||
this.isVehicleProtected = null;
|
||||
},
|
||||
setServiceabilityDetails(serviceabilityDetails) {
|
||||
this.isGlassServiceableInshop =
|
||||
serviceabilityDetails.isGlassServiceableInshop;
|
||||
|
|
@ -501,6 +511,9 @@ export default {
|
|||
serviceabilityDetails.isGlassServiceableMobile;
|
||||
this.isRecalibrationServiceableMobile =
|
||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||
if (!this.isServiceableMobile) {
|
||||
this.selectedAppointmentType = AppointmentTypeStrings.IN_SHOP;
|
||||
}
|
||||
},
|
||||
async updateMobileZip() {
|
||||
this.mobileZipError = '';
|
||||
|
|
@ -510,8 +523,10 @@ export default {
|
|||
if (!zipCodeData.isValid) {
|
||||
this.mobileZipError = errorMessages.INVALID_ZIP;
|
||||
} else if (!zipCodeData.isServiceable) {
|
||||
this.mobileZipError = errorMessages.NO_SERVICE_IN_ZIP(this.mobileZipCode);
|
||||
this.mobileZipError = errorMessages.NO_SERVICE_IN_AREA(toTitleCase(zipCodeData.city));
|
||||
} else {
|
||||
console.log('zipCodeData:', zipCodeData);
|
||||
this.city = zipCodeData.city;
|
||||
this.zipCode = this.mobileZipCode;
|
||||
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
||||
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
||||
|
|
@ -532,6 +547,9 @@ export default {
|
|||
if(providers.shopProviders.length > 0) {
|
||||
this.selectedProvider = providers.shopProviders[0];
|
||||
}
|
||||
else {
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -539,6 +557,8 @@ export default {
|
|||
async handleInShopZipUpdated(newZip) {
|
||||
this.zipCode = newZip;
|
||||
const zipCodeData = await getZipCodeData(this.zipCode);
|
||||
console.log('zipCodeData:', zipCodeData);
|
||||
this.city = zipCodeData.city;
|
||||
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
||||
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
||||
|
||||
|
|
@ -547,7 +567,6 @@ export default {
|
|||
const details = result.data;
|
||||
if (details) {
|
||||
this.setServiceabilityDetails(details);
|
||||
this.showMobileOption = this.isServiceableMobile;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -589,6 +608,11 @@ $page-side-padding: 1.5rem;
|
|||
margin-bottom: 1rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.625rem;
|
||||
flex-direction: column;
|
||||
.recal-text {
|
||||
margin-bottom: 1.25rem;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
.mobile-service-zip-question {
|
||||
:deep(.form-test-error span) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,9 @@
|
|||
class="shop-address"
|
||||
aria-live="polite">
|
||||
<div class="address-header">{{ questionText }}</div>
|
||||
<div class="current-address">
|
||||
<div
|
||||
v-if="modelValue"
|
||||
class="current-address">
|
||||
<div class="address-line">
|
||||
<span class="shop-name">{{ displayedShopName }}</span>
|
||||
<span class="shop-distance">{{ modelValue.distanceInMiles?.toFixed(2) }} mi</span>
|
||||
|
|
@ -16,10 +18,22 @@
|
|||
{{ getProviderCityZipState(modelValue) }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="no-shops-found">
|
||||
{{ `No shops found within 100 miles of ${internalZipcode}` }}
|
||||
</div>
|
||||
<buttonMain
|
||||
class="more-shops-button"
|
||||
:buttonText="showMoreShopsLinkText"
|
||||
:variant="'primary'"
|
||||
@clickEvent="openModal" />
|
||||
<alert
|
||||
class="alert-shop-distance"
|
||||
v-if="modelValue?.distanceInMiles > 30"
|
||||
ref="alertShopDistance"
|
||||
cmsWidgetName="AlertShopDistanceWidget"
|
||||
alertClass="alert-warning" />
|
||||
<modal
|
||||
:ref="modalName"
|
||||
:headerText="modalHeaderText"
|
||||
|
|
@ -129,7 +143,7 @@ export default {
|
|||
toTitleCase,
|
||||
serviceZipCodeTextInputId: '',
|
||||
internalZipcode: this.serviceZipcode,
|
||||
internalProviderNumber: this.modelValue.providerNumber,
|
||||
internalProviderNumber: this.modelValue?.providerNumber,
|
||||
searchRadiusQuestionWidgetName: 'SearchRadiusQuestionWidget',
|
||||
textboxQuestionWidgetName: 'ChangeLocationZipQuestionWidget',
|
||||
shopListButton: markRaw(shopListButton),
|
||||
|
|
@ -335,6 +349,18 @@ export default {
|
|||
.current-address {
|
||||
margin: .625rem 0;
|
||||
}
|
||||
.no-shops-found {
|
||||
font-size: .75rem;
|
||||
margin: .75rem 0rem;
|
||||
font-weight: $font-weight-bold;
|
||||
line-height: 1.375rem;
|
||||
}
|
||||
.more-shops-button {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.alert-shop-distance {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
:deep(.modal-title) {
|
||||
font-weight: 400;
|
||||
display: block;
|
||||
|
|
|
|||
|
|
@ -212,6 +212,8 @@ $alert-color-scale: 40%;
|
|||
|
||||
$alert-yellow-bg: #fef6e8;
|
||||
$alert-yellow-color: #e86421;
|
||||
$alert-red-bg: #fbe9e8;
|
||||
$alert-red-color: $red;
|
||||
|
||||
//Modal animation
|
||||
// This affects all [Bootstrap] modals
|
||||
|
|
|
|||
|
|
@ -41,17 +41,18 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="alert-body"
|
||||
v-show="alertCopy"
|
||||
:id="collapseId">
|
||||
<template
|
||||
v-for="paragraph in splitAlertCopyForParagraphTag"
|
||||
:key="paragraph">
|
||||
<p
|
||||
v-if="!doesCopyContainRouterLink(paragraph) && !doesCopyContainTextLink(paragraph)"
|
||||
class="m-0 text-body small"
|
||||
class="m-0 text-body"
|
||||
v-html="paragraph"></p>
|
||||
<p
|
||||
v-else
|
||||
class="m-0 text-body small">
|
||||
class="m-0 text-body">
|
||||
<template v-if="doesCopyContainRouterLink(paragraph)">
|
||||
<textBlock
|
||||
:customText="paragraph"
|
||||
|
|
@ -162,8 +163,9 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
this.ensureAlertIsInViewPort();
|
||||
this.collapseElement = Collapse.getOrCreateInstance(document.getElementById(this.collapseId));
|
||||
|
||||
if (this.isCollapsible) {
|
||||
this.collapseElement = Collapse.getOrCreateInstance(document.getElementById(this.collapseId));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doesCopyContainRouterLink,
|
||||
|
|
@ -234,8 +236,9 @@ export default {
|
|||
height: 100%;
|
||||
width: 100%;
|
||||
transition: transform 0.3s;
|
||||
transform: rotate(180deg);
|
||||
&.rotated {
|
||||
transform: rotate(180deg);
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
a {
|
||||
|
|
@ -271,10 +274,10 @@ export default {
|
|||
}
|
||||
}
|
||||
&.alert-danger {
|
||||
background-color: $red-100;
|
||||
border-color: $red-200;
|
||||
background-color: $alert-red-bg;
|
||||
border-color: $alert-red-color;
|
||||
.alert-body {
|
||||
border-top-color: $red-200;
|
||||
border-top-color: $alert-red-color;
|
||||
}
|
||||
svg {
|
||||
fill: $red-600;
|
||||
|
|
|
|||
Loading…
Reference in a new issue