Some updates for validation on zip entry/shop search
This commit is contained in:
parent
21e9127b50
commit
d85c0f6c38
16 changed files with 255 additions and 512 deletions
|
|
@ -25,6 +25,11 @@ const errorMessages = Object.freeze({
|
|||
EMAIL_ADDRESS_FORMAT: 'Please enter a valid email address.',
|
||||
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.`,
|
||||
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.',
|
||||
VIN_REQUIRED: 'Please enter your VIN',
|
||||
VIN_FORMAT:
|
||||
// eslint-disable-next-line max-len
|
||||
|
|
|
|||
|
|
@ -294,6 +294,11 @@ export default {
|
|||
this.resetField({
|
||||
value: newValue
|
||||
});
|
||||
},
|
||||
answers() {
|
||||
this.resetField({
|
||||
value: this.modelValue
|
||||
});
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
|
|
|||
|
|
@ -86,6 +86,10 @@ export default {
|
|||
modalPosition: {
|
||||
type: String,
|
||||
default: modalPositions.edge
|
||||
},
|
||||
allowInvalidSubmit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
emits: ['footer-button-event', 'isModalOpened'],
|
||||
|
|
@ -123,7 +127,7 @@ export default {
|
|||
methods: {
|
||||
async validateAndEmit() {
|
||||
const validationResult = await this.validate();
|
||||
if (validationResult.valid) {
|
||||
if (validationResult.valid || this.allowInvalidSubmit) {
|
||||
this.$emit('footer-button-event');
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export default {
|
|||
props: {
|
||||
customText: String, // used to allow the insert of token values into textblock
|
||||
justifyText: String, // left, right, center
|
||||
typeStyle: String, // h1-h6, body, small, label, caption
|
||||
typeStyle: String, // h1-h6, body, small, label, caption, disclaimer
|
||||
// (see Figma or Confluence documentation)
|
||||
fontWeight: String, // bold=500, default is 400
|
||||
cmsWidgetName: String,
|
||||
|
|
@ -109,5 +109,12 @@ export default {
|
|||
&.dark {
|
||||
color: $black;
|
||||
}
|
||||
&.disclaimer {
|
||||
color: $lighter-gray;
|
||||
font-weight: $font-weight-light;
|
||||
font-size: .8125rem;
|
||||
font-style: italic;
|
||||
margin-top: .625rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -250,8 +250,10 @@ export default {
|
|||
this.$emit('click-event');
|
||||
}
|
||||
},
|
||||
clickedTextButton() {
|
||||
if (this.meta.valid) {
|
||||
async clickedTextButton() {
|
||||
const result = await validate(this.value, this.validationRules);
|
||||
if (result.valid) {
|
||||
this.handleChange(this.value);
|
||||
this.$emit('click-event');
|
||||
}
|
||||
}
|
||||
|
|
@ -378,8 +380,8 @@ input::-webkit-date-and-time-value {
|
|||
.form-control {
|
||||
border: $border-input;
|
||||
border-radius: $border-radius;
|
||||
min-height: 3rem;
|
||||
max-height: 3rem;
|
||||
min-height: 2.8125rem;
|
||||
max-height: 2.8125rem;
|
||||
padding: 0.75rem 1rem;
|
||||
letter-spacing: inherit;
|
||||
box-shadow: $box-shadow-input;
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export default {
|
|||
const { AdvancedMarkerElement, PinElement } = await window.google.maps.importLibrary('marker');
|
||||
markers?.forEach((marker, index) => {
|
||||
const pinElement = new PinElement({
|
||||
glyph: String.fromCharCode('A'.charCodeAt(0) + index),
|
||||
glyphText: String.fromCharCode('A'.charCodeAt(0) + index),
|
||||
glyphColor: '#000000',
|
||||
borderColor: '#000000'
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
exports[`Shop list button should render correctly with all relevant props 1`] = `
|
||||
<transition-stub name="fade" mode="out-in" appear="false" persisted="false" css="true" selectedvalue="selected value">
|
||||
<base-input-button-stub modelvalue="value of modal" groupname="name of group" buttonwrapperclasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2" ismultiselect="false" validationrules="" isrequired="true" selectinginitiatesload="false" suppresserror="false" buttonlabel="Label of button" buttonlabelsubcopy="Sub copy of button" buttonbodycopy="button body copy" screenreaderonlytext="screen reader only text" additionalbuttondata="[object Object]" alttext="" iswide="false" value="1234"></base-input-button-stub>
|
||||
<base-input-button-stub modelvalue="value of modal" groupname="name of group" buttonwrapperclasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 no-hover" ismultiselect="false" validationrules="" isrequired="true" selectinginitiatesload="false" suppresserror="false" buttonlabel="Label of button" buttonlabelsubcopy="Sub copy of button" buttonbodycopy="button body copy" screenreaderonlytext="screen reader only text" additionalbuttondata="[object Object]" alttext="" iswide="false" value="1234"></base-input-button-stub>
|
||||
</transition-stub>
|
||||
`;
|
||||
|
||||
exports[`Shop list button should render correctly with required props 1`] = `
|
||||
<transition-stub name="fade" mode="out-in" appear="false" persisted="false" css="true">
|
||||
<base-input-button-stub modelvalue="value of modal" groupname="name of group" buttonwrapperclasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2" ismultiselect="false" validationrules="" isrequired="true" selectinginitiatesload="false" suppresserror="false" alttext="" iswide="false" value="1234"></base-input-button-stub>
|
||||
<base-input-button-stub modelvalue="value of modal" groupname="name of group" buttonwrapperclasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 no-hover" ismultiselect="false" validationrules="" isrequired="true" selectinginitiatesload="false" suppresserror="false" alttext="" iswide="false" value="1234"></base-input-button-stub>
|
||||
</transition-stub>
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -57,16 +57,12 @@ export default {
|
|||
return retCms;
|
||||
},
|
||||
answersToDisplay() {
|
||||
const shouldShowMobile = this.isServiceableMobile && this.isItacOrNoComp;
|
||||
const shouldShowMobileNotITACNotNoComp = this.isServiceableMobile && !this.isItacOrNoComp;
|
||||
const shouldShowMobile = this.isServiceableMobile;
|
||||
const shouldShowInshop = this.isServiceableInshop;
|
||||
const shouldShowDropoff = this.isServiceableInshop && !useMainStore().damage.isRepair;
|
||||
return this.answersFromCms
|
||||
? this.answersFromCms.filter((answer) => (
|
||||
(answer.Name === AppointmentTypeStrings.IN_SHOP && shouldShowInshop)
|
||||
|| (answer.Name === AppointmentTypeStrings.MOBILE && shouldShowMobile)
|
||||
|| (answer.Name === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP && shouldShowMobileNotITACNotNoComp)
|
||||
|| (answer.Name === AppointmentTypeStrings.DROP_OFF && shouldShowDropoff)
|
||||
))
|
||||
: [];
|
||||
},
|
||||
|
|
@ -97,14 +93,9 @@ export default {
|
|||
// If there is only one option to display and that option is 'Mobile' then select it
|
||||
if (
|
||||
newValue.length === 1
|
||||
&& newValue.findIndex((answer) => (answer.Name === AppointmentTypeStrings.MOBILE
|
||||
|| answer.Name === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP)) !== -1
|
||||
&& newValue.findIndex((answer) => (answer.Name === AppointmentTypeStrings.MOBILE)) !== -1
|
||||
) {
|
||||
if (this.isItacOrNoComp) {
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE;
|
||||
} else {
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
}
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE;
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
|
|
@ -112,11 +103,7 @@ export default {
|
|||
isMobileOnly: {
|
||||
handler(newValue) {
|
||||
if (newValue) {
|
||||
if (this.isItacOrNoComp) {
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE;
|
||||
} else {
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
}
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,26 +62,39 @@
|
|||
cmsWidgetName="AppointmentTypeQuestionWidget"
|
||||
validationRules="option-required" />
|
||||
</div>
|
||||
<mobileLocationModalQuestions
|
||||
v-if="isMobile"
|
||||
ref="mobileLocationQuestions"
|
||||
v-model="mobileLocationQuestions"
|
||||
customComponentId="mobileLocationQuestions"
|
||||
:mobileFeePart="mobileFeePart"
|
||||
validationRules="mobile-location-required"
|
||||
linkWidgetName="MobileLocationLinkWidget"
|
||||
modalWidgetName="MobileLocationModalWidget"
|
||||
@updated-mobile-fee-part="setMobileFeePart"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
@updated-contains-military-base="setContainsMilitaryBase"
|
||||
@updated-mobile-ctu="setCtuForMobile" />
|
||||
<shopAddress
|
||||
v-if="isInshop"
|
||||
v-model="selectedProvider"
|
||||
:serviceZipcode="zipCode"
|
||||
:isDisplayed="isInshop"
|
||||
:selectedAppointmentType="selectedAppointmentType"
|
||||
modalWidgetName="ChangeLocationModalWidget"
|
||||
cmsWidgetName="ShopAddressWidget" />
|
||||
cmsWidgetName="ShopAddressWidget"
|
||||
@zip-updated="handleInShopZipUpdated" />
|
||||
<div
|
||||
v-if="isMobile">
|
||||
<serviceZipQuestion
|
||||
ref="mobileServiceZipCodeQuestion"
|
||||
v-model="mobileZipCode"
|
||||
customInputId="mobileServiceZipCode"
|
||||
class="mobile-service-zip-question"
|
||||
:placeholderText="mobileZipPlaceholder"
|
||||
:serviceZipFormatErrorMessage="errorMessages.MOBILE_SERVICE_ZIP_FORMAT"
|
||||
:hasError="mobileZipError !== ''"
|
||||
cmsWidgetName="MobileZipWidget" />
|
||||
<div
|
||||
v-if="mobileZipError"
|
||||
ref="errorMessageDiv"
|
||||
class="row my-1 form-test-error">
|
||||
<span
|
||||
class="d-inline-flex mt-0"
|
||||
role="alert">{{ mobileZipError }}</span>
|
||||
</div>
|
||||
<textBlock
|
||||
v-if="displayMobileFeeDisclaimer"
|
||||
cmsWidgetName="MobileFeeDisclaimerWidget"
|
||||
typeStyle="disclaimer" />
|
||||
</div>
|
||||
<contentGroupModal
|
||||
:ref="RECAL_MODAL_REF_NAME"
|
||||
cssModalHeadlineClass="text-center"
|
||||
|
|
@ -111,35 +124,23 @@ import { useMainStore } from '@/store';
|
|||
import {
|
||||
getPricedMobileFeePart,
|
||||
getServiceabilityDetails,
|
||||
getZipCodeData
|
||||
getZipCodeData,
|
||||
getMobileZipCodeData
|
||||
} from '@/helpers/service-location-helper';
|
||||
|
||||
// Import Component
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||
import appointmentTypeQuestion from '@/layouts/service-location/appointment-type-question/appointment-type-question.vue';
|
||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
||||
import mobileLocationModalQuestions from '@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue';
|
||||
import { Form, defineRule } from 'vee-validate';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import shopAddress from './shop-address/shop-address.vue';
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule('mobile-location-required', (value) => {
|
||||
if (
|
||||
value.addressQuestions.streetAddress === ''
|
||||
|| value.addressQuestions.city === ''
|
||||
|| value.addressQuestions.state === ''
|
||||
|| value.addressQuestions.zipCode === ''
|
||||
|| value.isVehicleProtected == null
|
||||
) {
|
||||
return errorMessages.MOBILE_LOCATION_REQUIRED;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
defineRule('selection-required', required(errorMessages.OPTION_REQUIRED));
|
||||
import shopAddress from '@/layouts/service-location/shop-address/shop-address.vue';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
||||
import widgetFields from '@/constants/cms-widget-fields';
|
||||
|
||||
const RECAL_MODAL_REF_NAME = 'RecalModal';
|
||||
const SITE_FOOTER_REF_NAME = 'siteFooter';
|
||||
|
|
@ -148,15 +149,16 @@ export default {
|
|||
name: 'service-location',
|
||||
components: {
|
||||
alert,
|
||||
textBlock,
|
||||
appointmentTypeQuestion,
|
||||
contentGroupModal,
|
||||
mobileLocationModalQuestions,
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
shopAddress
|
||||
shopAddress,
|
||||
serviceZipQuestion
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -232,8 +234,12 @@ export default {
|
|||
mobileProviderNumber: null,
|
||||
zipContainsMilitaryBase: false,
|
||||
zipCodeCtu: null,
|
||||
mobileZipCode: '',
|
||||
mobileZipError: '',
|
||||
showMobileOption: false,
|
||||
RECAL_MODAL_REF_NAME,
|
||||
SITE_FOOTER_REF_NAME
|
||||
SITE_FOOTER_REF_NAME,
|
||||
errorMessages
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -246,35 +252,6 @@ export default {
|
|||
answersFromCms() {
|
||||
return this.getCmsContent('ServiceTypeQuestionWidget', 'Answers');
|
||||
},
|
||||
mobileLocationQuestions: {
|
||||
get() {
|
||||
return {
|
||||
addressQuestions: {
|
||||
streetAddress: this.streetAddress,
|
||||
streetAddress2: this.streetAddress2,
|
||||
city: this.city,
|
||||
state: this.state,
|
||||
zipCode: this.zipCode
|
||||
},
|
||||
isVehicleProtected: this.isVehicleProtected
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
this.streetAddress = newValue.addressQuestions.streetAddress;
|
||||
this.streetAddress2 = newValue.addressQuestions.streetAddress2;
|
||||
this.city = newValue.addressQuestions.city;
|
||||
this.state = newValue.addressQuestions.state;
|
||||
this.zipCode = newValue.addressQuestions.zipCode;
|
||||
this.isVehicleProtected = newValue.isVehicleProtected;
|
||||
|
||||
if (newValue.zipCode !== this.zipCode) {
|
||||
if (!this.isMobile) {
|
||||
this.selectedAppointmentType = null;
|
||||
}
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
isServiceableMobile() {
|
||||
if (this.isRecalibrationServiceableMobile !== null) {
|
||||
return (
|
||||
|
|
@ -301,15 +278,10 @@ export default {
|
|||
);
|
||||
},
|
||||
isAppointmentTypeDisplayed() {
|
||||
return this.zipCode && !this.displayNoShopsAlert;
|
||||
return this.zipCode && !this.displayNoShopsAlert && this.showMobileOption;
|
||||
},
|
||||
isMobile() {
|
||||
return (
|
||||
this.selectedAppointmentType
|
||||
=== AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType
|
||||
=== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
);
|
||||
return this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
},
|
||||
requiresInshopRecalibration() {
|
||||
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
|
||||
|
|
@ -341,6 +313,9 @@ export default {
|
|||
displayServiceableMobileOnly() {
|
||||
return this.isServiceableMobile && !this.isServiceableInshop;
|
||||
},
|
||||
displayMobileFeeDisclaimer() {
|
||||
return this.mainStore.isNoComp || this.mainStore.isITAC;
|
||||
},
|
||||
navigateBackScenario() {
|
||||
const { isNoComp, isITAC } = useMainStore();
|
||||
return isNoComp || isITAC
|
||||
|
|
@ -349,7 +324,10 @@ export default {
|
|||
},
|
||||
isBigTruck() {
|
||||
return this.mainStore.order.vehicle.isBigTruck;
|
||||
}
|
||||
},
|
||||
mobileZipPlaceholder() {
|
||||
return this.getCmsContent('MobileZipPlaceHolderWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
|
|
@ -445,6 +423,7 @@ export default {
|
|||
|
||||
if (serviceabilityDetails) {
|
||||
this.setServiceabilityDetails(serviceabilityDetails);
|
||||
this.showMobileOption = this.isServiceableMobile;
|
||||
}
|
||||
|
||||
if (mobileFeePart) {
|
||||
|
|
@ -503,6 +482,65 @@ export default {
|
|||
serviceabilityDetails.isGlassServiceableMobile;
|
||||
this.isRecalibrationServiceableMobile =
|
||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||
},
|
||||
async updateMobileZip() {
|
||||
this.mobileZipError = '';
|
||||
|
||||
const zipCodeData = await getMobileZipCodeData(this.mobileZipCode);
|
||||
|
||||
if (!zipCodeData.isValid) {
|
||||
this.mobileZipError = errorMessages.INVALID_ZIP;
|
||||
} else if (!zipCodeData.isServiceable) {
|
||||
this.mobileZipError = errorMessages.NO_SERVICE_IN_ZIP(this.mobileZipCode);
|
||||
} else {
|
||||
this.zipCode = this.mobileZipCode;
|
||||
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
||||
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
||||
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(this.mobileZipCode);
|
||||
serviceabilityDetailsPromise.then((result) => {
|
||||
const details = result.data;
|
||||
if (details) {
|
||||
this.setServiceabilityDetails(details);
|
||||
}
|
||||
});
|
||||
|
||||
const providersPromise = useMainStore().getProviders(this.mobileZipCode);
|
||||
providersPromise.then((result) => {
|
||||
const providers = result.data;
|
||||
if (providers) {
|
||||
this.setMobileProviderNumber(providers.mobileProviderNumber);
|
||||
if(providers.shopProviders.length > 0) {
|
||||
this.selectedProvider = providers.shopProviders[0];
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
async handleInShopZipUpdated(newZip) {
|
||||
this.zipCode = newZip;
|
||||
const zipCodeData = await getZipCodeData(this.zipCode);
|
||||
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
||||
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
||||
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(this.zipCode);
|
||||
serviceabilityDetailsPromise.then((result) => {
|
||||
const details = result.data;
|
||||
if (details) {
|
||||
this.setServiceabilityDetails(details);
|
||||
this.showMobileOption = this.isServiceableMobile;
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
mobileZipCode(newZip) {
|
||||
if(newZip !== '') {
|
||||
this.updateMobileZip();
|
||||
}
|
||||
},
|
||||
selectedAppointmentType() {
|
||||
this.mobileZipCode = '';
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -510,7 +548,6 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
$page-side-padding: 1.5rem;
|
||||
|
||||
.iss-heritage-container-width {
|
||||
.service-location-container {
|
||||
position: relative;
|
||||
|
|
@ -524,42 +561,12 @@ $page-side-padding: 1.5rem;
|
|||
.subheader {
|
||||
margin: 1.25rem 0;
|
||||
}
|
||||
}
|
||||
|
||||
.question-text {
|
||||
span {
|
||||
line-height: 1.5rem;
|
||||
text-align: center;
|
||||
.form-test-error {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
.list-card-content p {
|
||||
&:first-of-type {
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
&:not(:nth-of-type(1)) {
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
.choose-option {
|
||||
.button-question > div {
|
||||
&:first-of-type {
|
||||
margin-bottom: 0.95rem;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-question {
|
||||
.row.form-test-error {
|
||||
line-height: 1.5rem;
|
||||
padding-left: 0rem !important;
|
||||
}
|
||||
}
|
||||
.service-location-button-question {
|
||||
.question-text {
|
||||
margin-top: 1.5rem;
|
||||
|
||||
span {
|
||||
text-align: center;
|
||||
.mobile-service-zip-question {
|
||||
:deep(.form-test-error span) {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
||||
|
||||
describe('service-zip-question.vue', () => {
|
||||
it('Should get the modelValue', async () => {
|
||||
|
|
@ -12,8 +13,8 @@ describe('service-zip-question.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
const modelValueText = wrapper.vm.value;
|
||||
wrapper.vm.value = 'test also';
|
||||
const modelValueText = wrapper.vm.internalZipcode;
|
||||
wrapper.vm.internalZipcode = 'test also';
|
||||
|
||||
// Assert
|
||||
expect(modelValueText).toEqual('test');
|
||||
|
|
@ -30,7 +31,8 @@ describe('service-zip-question.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
wrapper.vm.value = 'test also';
|
||||
wrapper.vm.internalZipcode = 'test also';
|
||||
wrapper.vm.updateModelValue();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.emitted('update:modelValue')).toEqual([['test also']]);
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@
|
|||
cornerStyle="rounded"
|
||||
mask="#####"
|
||||
isRequired
|
||||
:hasError="hasError"
|
||||
@clickEvent="updateModelValue"
|
||||
validationRules="zip-required|zip-format" />
|
||||
</template>
|
||||
|
|
@ -21,7 +22,6 @@ import errorMessages from '@/constants/error-messages';
|
|||
|
||||
// Define Validation Rules
|
||||
defineRule('zip-required', required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||
defineRule('zip-format', regex(/^\d{5}$/, errorMessages.SERVICE_ZIP_FORMAT));
|
||||
|
||||
export default {
|
||||
name: 'service-zip-question',
|
||||
|
|
@ -31,7 +31,15 @@ export default {
|
|||
// TODO: Correct prop def.
|
||||
props: {
|
||||
modelValue: String,
|
||||
cmsWidgetName: String
|
||||
cmsWidgetName: String,
|
||||
serviceZipFormatErrorMessage: {
|
||||
type: String,
|
||||
default: errorMessages.SERVICE_ZIP_FORMAT
|
||||
},
|
||||
hasError: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
|
@ -42,16 +50,20 @@ export default {
|
|||
methods: {
|
||||
updateModelValue() {
|
||||
this.$emit('update:modelValue', this.internalZipcode);
|
||||
this.internalZipcode = '';
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
defineRule('zip-format', regex(/^\d{5}$/, this.serviceZipFormatErrorMessage));
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.textbox-question {
|
||||
:deep(.form-label) {
|
||||
font-weight: $font-weight-normal;
|
||||
color: $darker-gray;
|
||||
<style lang="scss" scoped>
|
||||
.textbox-question.has-success {
|
||||
:deep(input.form-control) {
|
||||
border: $border-input;
|
||||
&:focus {
|
||||
border: $border-input-focus;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -6,13 +6,6 @@
|
|||
v-if="isDisplayed"
|
||||
class="shop-address"
|
||||
aria-live="polite">
|
||||
<alert
|
||||
v-if="displayDropoffInformation"
|
||||
ref="alertDropoffInformation"
|
||||
class="mb-4 drop-off-alert"
|
||||
cmsWidgetName="AlertDropoffInformationWidget"
|
||||
alertClass="alert-info"
|
||||
:isDismissible="false" />
|
||||
<div class="address-header">{{ questionText }}</div>
|
||||
<div class="current-address">
|
||||
<div class="address-line">
|
||||
|
|
@ -32,9 +25,9 @@
|
|||
:ref="modalName"
|
||||
:headerText="modalHeaderText"
|
||||
:onModalOpenedCallback="onModalOpened"
|
||||
:onModalClosedCallback="onModalClosed"
|
||||
:footerButtonText="modalFooterText"
|
||||
:modalPosition="modalPositions.center"
|
||||
:allowInvalidSubmit="true"
|
||||
@footerButtonEvent="updateSelectedProvider">
|
||||
<googleMap
|
||||
id="map"
|
||||
|
|
@ -49,7 +42,7 @@
|
|||
:variant="dropdownVariants.compact"
|
||||
:options="searchRadiusOptions" />
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
ref="shopListButtonQuestion"
|
||||
v-model="internalProviderNumber"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
|
|
@ -65,17 +58,18 @@
|
|||
</span>
|
||||
<serviceZipQuestion
|
||||
v-if="renderServiceZip"
|
||||
ref="serviceZipCodeQuestion"
|
||||
:ref="SERVICE_ZIP_QUESTION_REF_NAME"
|
||||
v-model="internalZipcode"
|
||||
customInputId="serviceZipCode"
|
||||
:cmsWidgetName="textboxQuestionWidgetName" />
|
||||
<alert
|
||||
v-if="displayInvalidZipAlert"
|
||||
ref="alertInvalidZip"
|
||||
class="my-4"
|
||||
:cmsWidgetName="alertInvalidZipWidgetName"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<div
|
||||
v-if="errorMessage"
|
||||
ref="errorMessageDiv"
|
||||
class="row my-1 form-test-error">
|
||||
<span
|
||||
class="d-inline-flex mt-0"
|
||||
role="alert">{{ errorMessage }}</span>
|
||||
</div>
|
||||
</modal>
|
||||
</div>
|
||||
</transition>
|
||||
|
|
@ -96,11 +90,17 @@ import googleMap from '@/iss-components/google-map/google-map.vue';
|
|||
import baseMixin from '@/mixins/base-mixin.js';
|
||||
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||
import { markRaw } from 'vue';
|
||||
import { getServiceabilityDetails, getZipCodeData,getAvailabilityRating } from '@/helpers/service-location-helper';
|
||||
import { getAvailabilityRating } from '@/helpers/service-location-helper';
|
||||
import { useMainStore } from '@/store';
|
||||
import widgetFields from '@/constants/cms-widget-fields';
|
||||
import { dropdownVariants, modalPositions } from '@/constants/component-variants';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
|
||||
defineRule('option-required', required(errorMessages.PROVIDER_REQUIRED));
|
||||
|
||||
const SERVICE_ZIP_QUESTION_REF_NAME = 'serviceZipCodeQuestion';
|
||||
|
||||
export default {
|
||||
name: 'shop-address',
|
||||
|
|
@ -130,21 +130,21 @@ export default {
|
|||
return {
|
||||
toTitleCase,
|
||||
serviceZipCodeTextInputId: '',
|
||||
displayInvalidZipAlert: false,
|
||||
internalZipcode: this.serviceZipcode,
|
||||
internalProviderNumber: this.modelValue.providerNumber,
|
||||
searchRadiusQuestionWidgetName: 'SearchRadiusQuestionWidget',
|
||||
textboxQuestionWidgetName: 'ChangeLocationZipQuestionWidget',
|
||||
alertInvalidZipWidgetName: 'AlertInvalidZipWidget',
|
||||
shopListButton: markRaw(shopListButton),
|
||||
searchRadiusInMiles: 100,
|
||||
searchRadiusInMiles: "25",
|
||||
nearbyShops: [],
|
||||
modalPositions,
|
||||
dropdownVariants,
|
||||
renderServiceZip: true
|
||||
renderServiceZip: true,
|
||||
errorMessage: '',
|
||||
SERVICE_ZIP_QUESTION_REF_NAME
|
||||
};
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
emits: ['update:modelValue', 'zip-updated'],
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT);
|
||||
|
|
@ -199,12 +199,17 @@ export default {
|
|||
};
|
||||
});
|
||||
},
|
||||
searchRadiusOptions() {
|
||||
searchRadiusArray() {
|
||||
const options = this.getCmsContent(this.searchRadiusQuestionWidgetName, widgetFields.INPUT_QUESTION_WIDGET.ANSWERS);
|
||||
return options;
|
||||
},
|
||||
searchRadiusOptions() {
|
||||
const optionsObj = {};
|
||||
options.forEach(option => {
|
||||
optionsObj[option.Name] = option.Text;
|
||||
});
|
||||
if(this.searchRadiusArray) {
|
||||
this.searchRadiusArray.forEach(option => {
|
||||
optionsObj[option.Name] = option.Text;
|
||||
});
|
||||
}
|
||||
return optionsObj;
|
||||
},
|
||||
providerAddresses() {
|
||||
|
|
@ -217,19 +222,30 @@ export default {
|
|||
},
|
||||
watch: {
|
||||
async internalZipcode() {
|
||||
await this.resetsOnZipInput();
|
||||
const shopsUpdated = await this.updateShops();
|
||||
if (shopsUpdated) {
|
||||
this.$refs[SERVICE_ZIP_QUESTION_REF_NAME].internalZipcode = '';
|
||||
}
|
||||
},
|
||||
async searchRadiusInMiles() {
|
||||
this.nearbyShops = await this.getNearbyShops(this.searchRadiusInMiles);
|
||||
await this.updateShops();
|
||||
},
|
||||
nearbyShops(newShops) {
|
||||
if (!newShops.find(shop => shop.providerNumber === this.internalProviderNumber)) {
|
||||
this.internalProviderNumber = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
resetAlerts() {
|
||||
this.displayInvalidZipAlert = false;
|
||||
},
|
||||
async resetsOnZipInput() {
|
||||
this.resetAlerts();
|
||||
this.nearbyShops = await this.getNearbyShops(this.searchRadiusInMiles);
|
||||
async updateShops() {
|
||||
this.errorMessage = '';
|
||||
const result = await this.getNearbyShops(this.searchRadiusInMiles);
|
||||
if (result.length === 0) {
|
||||
this.errorMessage = errorMessages.ZIP_CODE_NOT_SERVICED_FOR_VEHICLE;
|
||||
}
|
||||
else {
|
||||
this.nearbyShops = await this.getNearbyShops(this.searchRadiusInMiles);
|
||||
}
|
||||
},
|
||||
openModal() {
|
||||
this.$refs[this.modalName].openModal();
|
||||
|
|
@ -239,26 +255,19 @@ export default {
|
|||
},
|
||||
onModalOpened() {
|
||||
this.internalZipcode = this.serviceZipcode;
|
||||
this.searchRadiusInMiles = 25;
|
||||
this.resetsOnZipInput().then(() => {
|
||||
this.searchRadiusInMiles = "25";
|
||||
this.updateShops().then(() => {
|
||||
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
|
||||
});
|
||||
this.forceServiceZipRerender();
|
||||
},
|
||||
onModalClosed() {
|
||||
this.internalZipcode = this.serviceZipcode;
|
||||
this.resetsOnZipInput().then(() => {
|
||||
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
|
||||
});
|
||||
},
|
||||
async updateSelectedProvider() {
|
||||
if (this.internalProviderNumber !== this.modelValue.providerNumber) {
|
||||
const selectedShop = this.nearbyShops.find(shop => shop.providerNumber === this.internalProviderNumber);
|
||||
if (selectedShop) {
|
||||
this.$emit('update:modelValue', selectedShop);
|
||||
}
|
||||
const selectedShop = this.nearbyShops.find(shop => shop.providerNumber === this.internalProviderNumber);
|
||||
if (selectedShop) {
|
||||
this.$emit('update:modelValue', selectedShop);
|
||||
this.$emit('zip-updated', this.internalZipcode);
|
||||
this.closeModal();
|
||||
}
|
||||
this.closeModal();
|
||||
},
|
||||
async getNearbyShops(radiusInMiles) {
|
||||
const result = await useMainStore().getProviders(this.internalZipcode, radiusInMiles);
|
||||
|
|
@ -336,5 +345,22 @@ export default {
|
|||
:deep(#map) {
|
||||
height: 27rem;
|
||||
}
|
||||
:deep(.textbox-question) {
|
||||
&.has-error {
|
||||
input.form-control {
|
||||
border: $border-input;
|
||||
&:focus {
|
||||
border: $border-input-focus;
|
||||
}
|
||||
}
|
||||
}
|
||||
.form-label {
|
||||
font-weight: $font-weight-normal;
|
||||
color: $darker-gray;
|
||||
}
|
||||
.btn-primary {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,294 +0,0 @@
|
|||
<template>
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
v-if="isDisplayed"
|
||||
class="shop-question"
|
||||
aria-live="polite">
|
||||
<alert
|
||||
v-if="displayDropoffInformation"
|
||||
ref="alertDropoffInformation"
|
||||
class="mb-4 drop-off-alert"
|
||||
cmsWidgetName="AlertDropoffInformationWidget"
|
||||
alertClass="alert-info"
|
||||
:isDismissible="false" />
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-model="selectedProviderNumber"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
class="radioQuestion"
|
||||
:questionText="questionText"
|
||||
:answers="answers"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start"
|
||||
isRequired
|
||||
validationRules="option-required"
|
||||
:additionalButtonData="additionalButtonData" />
|
||||
<textLink
|
||||
v-show="displaySeeMoreLocationsLink"
|
||||
id="showMoreShopsId"
|
||||
ref="showMoreShopsLink"
|
||||
class="show-more-shops-link"
|
||||
cmsWidgetName="ShowMoreShopsLinkWidget"
|
||||
linkType="text"
|
||||
:text="showMoreShopsLinkText"
|
||||
href="#!"
|
||||
:aria-label="showMoreShopsLinkText"
|
||||
@clickEvent="getNextShopsFromList" />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||
|
||||
// Supporting files
|
||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
||||
import baseMixin from '@/mixins/base-mixin.js';
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import { useMainStore } from '@/store/index.js';
|
||||
import { markRaw, nextTick } from 'vue';
|
||||
import { getAvailabilityRating } from '@/helpers/service-location-helper';
|
||||
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
||||
|
||||
defineRule('option-required', required(errorMessages.OPTION_REQUIRED));
|
||||
|
||||
export default {
|
||||
name: 'shop-question',
|
||||
components: {
|
||||
alert,
|
||||
buttonQuestion,
|
||||
textLink
|
||||
},
|
||||
mixins: [baseMixin],
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => null
|
||||
},
|
||||
selectedAppointmentType: String,
|
||||
cmsWidgetName: String,
|
||||
validationRules: String,
|
||||
isDisplayed: Boolean
|
||||
},
|
||||
emits: ['update:modelValue', 'updatedMobileProviderNumber'],
|
||||
data() {
|
||||
return {
|
||||
shopProviders: [],
|
||||
shopListButton: markRaw(shopListButton),
|
||||
answers: [],
|
||||
shopIndex: 0,
|
||||
displaySeeMoreLocationsLink: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||
},
|
||||
selectedValue: {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
},
|
||||
selectedProviderNumber: {
|
||||
get() {
|
||||
return this.selectedValue?.providerNumber;
|
||||
},
|
||||
set(newValue) {
|
||||
// Button Question only supports Number, or String data types so we must get the full object to emit
|
||||
this.selectedValue = this.getSelectedProviderObject(newValue);
|
||||
}
|
||||
},
|
||||
displayDropoffInformation() {
|
||||
return this.selectedAppointmentType === 'Dropoff';
|
||||
},
|
||||
showMoreShopsLinkText() {
|
||||
return this.getCmsContent('ShowMoreShopsLinkWidget', 'Text');
|
||||
},
|
||||
additionalButtonData() {
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 6);
|
||||
|
||||
const formattedStartDate = startDate.toISOString().split('T')[0];
|
||||
const formattedEndDate = endDate.toISOString().split('T')[0];
|
||||
|
||||
return {
|
||||
displayAvailabilityIndicators: true,
|
||||
availabilityRatingCallback: getAvailabilityRating,
|
||||
startDate: formattedStartDate,
|
||||
endDate: formattedEndDate,
|
||||
shopAppointmentType: this.selectedAppointmentType
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedAppointmentType: {
|
||||
async handler(newValue) {
|
||||
this.resetAnswers();
|
||||
|
||||
await nextTick();
|
||||
|
||||
this.selectedProviderNumber = null;
|
||||
|
||||
await nextTick();
|
||||
|
||||
if (newValue !== AppointmentTypeStrings.MOBILE && newValue !== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
||||
this.getNextShopsFromList();
|
||||
}
|
||||
}
|
||||
},
|
||||
shopProviders: {
|
||||
async handler(newValue) {
|
||||
await nextTick();
|
||||
|
||||
if (this.selectedAppointmentType) {
|
||||
const selectedShopIndex = this.getSelectedProviderIndex(
|
||||
newValue,
|
||||
this.selectedProviderNumber
|
||||
);
|
||||
|
||||
if (selectedShopIndex >= 3) {
|
||||
await this.getNextShopsFromList(selectedShopIndex + 1);
|
||||
} else {
|
||||
await this.getNextShopsFromList();
|
||||
await nextTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadInitialData(serviceZipCode) {
|
||||
return this.loadData(serviceZipCode);
|
||||
},
|
||||
loadData(serviceZipCode) {
|
||||
return useMainStore().getProviders(serviceZipCode);
|
||||
},
|
||||
initializeComponent(shopQuestionInitialData) {
|
||||
this.shopProviders = shopQuestionInitialData.shopProviders;
|
||||
},
|
||||
async getNextShopsFromList(numberToGet = 3) {
|
||||
const shopIterator = (array, n) => {
|
||||
const l = array.length;
|
||||
return () => {
|
||||
const end = this.shopIndex + n;
|
||||
const part = array.slice(this.shopIndex, end);
|
||||
this.shopIndex = end < l ? end : this.shopProviders.length;
|
||||
return part;
|
||||
};
|
||||
};
|
||||
|
||||
const toTitleCase = (str) => str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
|
||||
|
||||
const nextShop = shopIterator(this.shopProviders, numberToGet);
|
||||
|
||||
// Map API result data
|
||||
const mappedData = nextShop().map((shopProvider) => {
|
||||
const streetAddress = toTitleCase(shopProvider.address.streetAddress);
|
||||
const city = toTitleCase(shopProvider.address.city);
|
||||
const { state } = shopProvider.address;
|
||||
const { zipCode } = shopProvider.address;
|
||||
const distanceInMiles = Math.round(shopProvider.distanceInMiles * 2) / 2;
|
||||
|
||||
return {
|
||||
buttonLabel: city,
|
||||
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
||||
buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
|
||||
value: shopProvider.providerNumber
|
||||
};
|
||||
});
|
||||
|
||||
if (this.answers.length === 0) {
|
||||
this.answers = mappedData;
|
||||
} else {
|
||||
mappedData.forEach((shop) => {
|
||||
this.answers.push(shop);
|
||||
});
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
if (this.shopIndex === this.shopProviders.length) {
|
||||
this.displaySeeMoreLocationsLink = false;
|
||||
} else {
|
||||
this.displaySeeMoreLocationsLink = true;
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
this.scrollToPageBottom();
|
||||
},
|
||||
resetAnswers() {
|
||||
this.answers = [];
|
||||
this.shopIndex = 0;
|
||||
},
|
||||
async reloadShopData(serviceZipCode) {
|
||||
const result = await this.loadData(serviceZipCode);
|
||||
this.initializeComponent(result.data);
|
||||
|
||||
if (result.data?.mobileProviderNumber
|
||||
&& (this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP)) {
|
||||
this.$emit('updatedMobileProviderNumber', result.data.mobileProviderNumber);
|
||||
}
|
||||
|
||||
this.resetAnswers();
|
||||
|
||||
await nextTick();
|
||||
await this.getNextShopsFromList();
|
||||
},
|
||||
getSelectedProviderObject(providerNumber) {
|
||||
const provider = this.shopProviders?.find((p) => p.providerNumber === providerNumber);
|
||||
return provider;
|
||||
},
|
||||
getSelectedProviderIndex(providers, selectedProviderNumber) {
|
||||
const index = providers.findIndex((p) => p.providerNumber === selectedProviderNumber);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/styles/ux-variables-svg-strings.scss";
|
||||
|
||||
.shop-question {
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
|
||||
.button-question {
|
||||
.question-text {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.drop-off-alert {
|
||||
background-image: url($svg-drop-off-alert);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 0.75rem;
|
||||
background-position: 0.5rem 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0.5rem 0.5rem 0.5rem 1.5rem !important;
|
||||
gap: 0.25rem;
|
||||
|
||||
.alert-heading {
|
||||
text-align: left;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1798,7 +1798,6 @@ export const useMainStore = defineStore({
|
|||
this.order.vehicle.registration.lastName = registrationInfo?.lastName;
|
||||
},
|
||||
updateServiceLocation(serviceLocationInfo) {
|
||||
console.log('Updating service location info:', serviceLocationInfo);
|
||||
this.order.serviceLocation.address = serviceLocationInfo.address;
|
||||
this.order.serviceLocation.address2 = serviceLocationInfo.address2;
|
||||
this.order.serviceLocation.city = serviceLocationInfo.city;
|
||||
|
|
@ -2708,7 +2707,6 @@ export const useMainStore = defineStore({
|
|||
},
|
||||
|
||||
saveServiceLocation(serviceLocationInfo) {
|
||||
console.log('Saving service location info:', serviceLocationInfo);
|
||||
if (this.order.serviceLocation) {
|
||||
if (
|
||||
serviceLocationInfo.zipCode !== this.order.serviceLocation.zipCode
|
||||
|
|
@ -2719,7 +2717,6 @@ export const useMainStore = defineStore({
|
|||
|| serviceLocationInfo.appointmentType
|
||||
!== this.order.serviceLocation.appointmentType
|
||||
) {
|
||||
console.log('Service location info has changed, resetting dependent state.');
|
||||
this.resetSchedule();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,21 +115,3 @@ caption,
|
|||
font-weight: 800;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Urbanist";
|
||||
src:
|
||||
url("@/assets/fonts/Urbanist-MediumItalic.woff2") format("woff2"),
|
||||
url("@/assets/fonts/Urbanist-MediumItalic.woff") format("woff");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Urbanist";
|
||||
src:
|
||||
url("@/assets/fonts/Urbanist-BoldItalic.woff2") format("woff2"),
|
||||
url("@/assets/fonts/Urbanist-BoldItalic.woff") format("woff");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
|
@ -76,6 +76,7 @@ $heritage-blue-secondary: #167cac;
|
|||
|
||||
// Darker gray
|
||||
$darker-gray: #525656;
|
||||
$lighter-gray: #9aa1a3;
|
||||
|
||||
// scss-docs-start colors-map
|
||||
$colors: (
|
||||
|
|
@ -220,5 +221,5 @@ $enable-important-utilities: false;
|
|||
// Letter Spacing
|
||||
$letter-spacing-primary: 0.03em;
|
||||
// Borders
|
||||
$border-input: 1px solid rgba(179, 180, 181);
|
||||
$border-input: 1px solid $gray-350;
|
||||
$border-input-focus: 2.5px solid $heritage-blue-primary;
|
||||
|
|
|
|||
Loading…
Reference in a new issue