Add search radius to change location modal + related style updates
This commit is contained in:
parent
6eab5c2040
commit
bcc156ec29
13 changed files with 113 additions and 47 deletions
|
|
@ -1,9 +0,0 @@
|
|||
const buttonVariants = Object.freeze({
|
||||
primary: 'primary',
|
||||
secondary: 'secondary',
|
||||
success: 'success',
|
||||
link: 'link',
|
||||
navigation: 'navigation'
|
||||
});
|
||||
|
||||
export default buttonVariants;
|
||||
15
src/constants/component-variants.js
Normal file
15
src/constants/component-variants.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export const buttonVariants = Object.freeze({
|
||||
primary: 'primary',
|
||||
secondary: 'secondary',
|
||||
success: 'success',
|
||||
link: 'link',
|
||||
navigation: 'navigation'
|
||||
});
|
||||
export const dropdownVariants = Object.freeze({
|
||||
primary: 'primary',
|
||||
compact: 'compact'
|
||||
});
|
||||
export const modalPositions = Object.freeze({
|
||||
center: 'center',
|
||||
edge: 'edge'
|
||||
});
|
||||
|
|
@ -23,8 +23,8 @@ const errorMessages = Object.freeze({
|
|||
LAST_NAME_REQUIRED: 'Please enter your last name',
|
||||
EMAIL_ADDRESS_REQUIRED: 'Email is required.',
|
||||
EMAIL_ADDRESS_FORMAT: 'Please enter a valid email address.',
|
||||
SERVICE_ZIP_REQUIRED: 'Please enter your service ZIP',
|
||||
SERVICE_ZIP_FORMAT: 'Please enter a valid service ZIP',
|
||||
SERVICE_ZIP_REQUIRED: 'ZIP code is required',
|
||||
SERVICE_ZIP_FORMAT: 'Invalid ZIP, please enter a new ZIP (5 characters)',
|
||||
VIN_REQUIRED: 'Please enter your VIN',
|
||||
VIN_FORMAT:
|
||||
// eslint-disable-next-line max-len
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@
|
|||
<div
|
||||
class="dropdown-question"
|
||||
:class="{
|
||||
'has-error' : (meta.touched && errors && errors.length && !isDisabled) || hasError,
|
||||
'has-success': (meta.touched && (!errors || !errors.length) && !isDisabled)
|
||||
'has-error' : (meta?.touched && errors && errors.length && !isDisabled) || hasError,
|
||||
'has-success': (meta?.touched && (!errors || !errors.length) && !isDisabled),
|
||||
[`dropdown-${variant}`]: true
|
||||
}">
|
||||
<label
|
||||
:for="inputId"
|
||||
|
|
@ -34,7 +35,7 @@
|
|||
</option>
|
||||
</select>
|
||||
<div
|
||||
v-show="meta.touched && errorMessage && !isDisabled"
|
||||
v-show="meta?.touched && errorMessage && !isDisabled"
|
||||
class="row mt-1 form-test-error">
|
||||
<span role="alert">{{ errorMessage }}</span>
|
||||
</div>
|
||||
|
|
@ -42,6 +43,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { dropdownVariants } from '@/constants/component-variants';
|
||||
import { useField } from 'vee-validate';
|
||||
|
||||
export default {
|
||||
|
|
@ -59,7 +61,11 @@ export default {
|
|||
validationRules: String,
|
||||
cmsWidgetName: String,
|
||||
hasError: Boolean,
|
||||
placeHolderText: String
|
||||
placeHolderText: String,
|
||||
variant: {
|
||||
type: String,
|
||||
default: dropdownVariants.primary
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props) {
|
||||
|
|
@ -154,5 +160,30 @@ export default {
|
|||
filter: grayscale(100%);
|
||||
}
|
||||
}
|
||||
&.dropdown-compact {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: end;
|
||||
margin-bottom: 1.25rem;
|
||||
.form-label {
|
||||
color: $darker-gray;
|
||||
font-weight: $font-weight-light;
|
||||
margin: 0;
|
||||
}
|
||||
.form-select {
|
||||
color: $heritage-blue-secondary;
|
||||
background-position-x: 98%;
|
||||
padding: 0;
|
||||
padding-left: .3125rem;
|
||||
width: 5.625rem;
|
||||
min-height: auto;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
border: .125rem solid $black;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@
|
|||
}">
|
||||
<div class="modal-dialog"
|
||||
:class="{
|
||||
'modal-dialog-edge': modalPosition === 'edge',
|
||||
'modal-dialog-centered': modalPosition === 'center'
|
||||
'modal-dialog-edge': modalPosition === modalPositions.edge,
|
||||
'modal-dialog-centered': modalPosition === modalPositions.center
|
||||
}">
|
||||
<div
|
||||
class="modal-content"
|
||||
|
|
@ -60,6 +60,7 @@
|
|||
import ButtonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import { Modal } from 'bootstrap';
|
||||
import { useForm } from 'vee-validate';
|
||||
import { modalPositions } from '@/constants/component-variants';
|
||||
|
||||
export default {
|
||||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
|
|
@ -84,7 +85,7 @@ export default {
|
|||
},
|
||||
modalPosition: {
|
||||
type: String,
|
||||
default: 'edge'
|
||||
default: modalPositions.edge
|
||||
}
|
||||
},
|
||||
emits: ['footer-button-event', 'isModalOpened'],
|
||||
|
|
@ -102,7 +103,8 @@ export default {
|
|||
modalId,
|
||||
meta,
|
||||
validate,
|
||||
resetForm
|
||||
resetForm,
|
||||
modalPositions
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@
|
|||
ref="buttonMain"
|
||||
variant="primary"
|
||||
:buttonText="buttonText"
|
||||
@clickEvent="buttonCallback">
|
||||
@clickEvent="clickedTextButton">
|
||||
</buttonMain>
|
||||
</div>
|
||||
<div
|
||||
|
|
@ -249,6 +249,11 @@ export default {
|
|||
if (this.meta.valid) {
|
||||
this.$emit('click-event');
|
||||
}
|
||||
},
|
||||
clickedTextButton() {
|
||||
if (this.meta.valid) {
|
||||
this.$emit('click-event');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -344,6 +349,13 @@ input::-webkit-date-and-time-value {
|
|||
display: flex;
|
||||
input[type='text'] {
|
||||
border-radius: 1.5rem;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
button {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
min-width: 6.875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ import coverageType from '@/constants/coverage-type';
|
|||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
import { buttonVariants } from '@/constants/component-variants';
|
||||
|
||||
export default {
|
||||
name: 'policy-vehicles',
|
||||
|
|
|
|||
|
|
@ -124,7 +124,6 @@ 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 serviceZipModalQuestion from '@/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue';
|
||||
import shopAddress from './shop-address/shop-address.vue';
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
|
|
@ -157,7 +156,6 @@ export default {
|
|||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
serviceZipModalQuestion,
|
||||
shopAddress
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
|
|
@ -169,7 +167,6 @@ export default {
|
|||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(serviceZipCode);
|
||||
const getGlassFeesPromise = useMainStore().getGlassFees();
|
||||
console.log('Fetching providers for zip code:', serviceZipCode);
|
||||
const providersPromise = useMainStore().getProviders(serviceZipCode);
|
||||
|
||||
// Settle promises and get results
|
||||
|
|
@ -417,9 +414,6 @@ export default {
|
|||
);
|
||||
},
|
||||
getServiceZipCodeFromStore() {
|
||||
console.log('Getting service zip code from store');
|
||||
console.log(useMainStore().order.serviceLocation.zipCode);
|
||||
console.log(useMainStore().order.customer.address.zipCode);
|
||||
return (
|
||||
useMainStore().order.serviceLocation.zipCode
|
||||
|| useMainStore().order.customer.address.zipCode
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue';
|
||||
|
||||
describe('service-zip-question.vue', () => {
|
||||
it('Should get the modelValue', async () => {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
cornerStyle="rounded"
|
||||
mask="#####"
|
||||
isRequired
|
||||
:buttonCallback="updateModelValue"
|
||||
@clickEvent="updateModelValue"
|
||||
validationRules="zip-required|zip-format" />
|
||||
</template>
|
||||
|
||||
|
|
|
|||
|
|
@ -34,8 +34,15 @@
|
|||
:onModalOpenedCallback="onModalOpened"
|
||||
:onModalClosedCallback="onModalClosed"
|
||||
:footerButtonText="modalFooterText"
|
||||
:modalPosition="'center'"
|
||||
:modalPosition="modalPositions.center"
|
||||
@footerButtonEvent="updateSelectedProvider">
|
||||
<dropdownQuestion
|
||||
inputId="searchRadiusDropdown"
|
||||
ref="searchRadiusQuestion"
|
||||
v-model="searchRadiusInMiles"
|
||||
:cmsWidgetName="searchRadiusQuestionWidgetName"
|
||||
:variant="dropdownVariants.compact"
|
||||
:options="searchRadiusOptions" />
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-model="internalProviderNumber"
|
||||
|
|
@ -55,8 +62,7 @@
|
|||
ref="serviceZipCodeQuestion"
|
||||
v-model="internalZipcode"
|
||||
customInputId="serviceZipCode"
|
||||
:cmsWidgetName="textboxQuestionWidgetName"
|
||||
v-on="{ 'textboxQuestionEvent.inputIdAssigned': onInputIdAssigned }" />
|
||||
:cmsWidgetName="textboxQuestionWidgetName" />
|
||||
<alert
|
||||
v-if="displayInvalidZipAlert"
|
||||
ref="alertInvalidZip"
|
||||
|
|
@ -77,6 +83,7 @@ import modal from '@/digital-components/modal/modal.vue';
|
|||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
||||
|
||||
// Supporting files
|
||||
import baseMixin from '@/mixins/base-mixin.js';
|
||||
|
|
@ -84,6 +91,8 @@ import { toTitleCase } from '@/helpers/text-helper.js';
|
|||
import { markRaw, nextTick } from 'vue';
|
||||
import { getServiceabilityDetails, getZipCodeData,getAvailabilityRating } from '@/helpers/service-location-helper';
|
||||
import { useMainStore } from '@/store';
|
||||
import widgetFields from '@/constants/cms-widget-fields';
|
||||
import { dropdownVariants, modalPositions } from '@/constants/component-variants';
|
||||
|
||||
|
||||
export default {
|
||||
|
|
@ -93,7 +102,8 @@ export default {
|
|||
buttonMain,
|
||||
modal,
|
||||
serviceZipQuestion,
|
||||
buttonQuestion
|
||||
buttonQuestion,
|
||||
dropdownQuestion
|
||||
},
|
||||
mixins: [baseMixin],
|
||||
props: {
|
||||
|
|
@ -115,32 +125,35 @@ export default {
|
|||
displayInvalidZipAlert: false,
|
||||
internalZipcode: this.serviceZipcode,
|
||||
internalProviderNumber: this.modelValue.providerNumber,
|
||||
searchRadiusQuestionWidgetName: 'SearchRadiusQuestionWidget',
|
||||
textboxQuestionWidgetName: 'ChangeLocationZipQuestionWidget',
|
||||
alertInvalidZipWidgetName: 'AlertInvalidZipWidget',
|
||||
shopListButton: markRaw(shopListButton),
|
||||
searchRadiusInMiles: 25,
|
||||
nearbyShops: []
|
||||
searchRadiusInMiles: 100,
|
||||
nearbyShops: [],
|
||||
modalPositions,
|
||||
dropdownVariants
|
||||
};
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||
return this.getCmsContent(this.cmsWidgetName, widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT);
|
||||
},
|
||||
showMoreShopsLinkText() {
|
||||
return this.getCmsContent('ShowMoreShopsLinkWidget', 'Text');
|
||||
return this.getCmsContent('ShowMoreShopsLinkWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
},
|
||||
displayedShopName() {
|
||||
if(this.modelValue.isSafeliteShop) {
|
||||
return this.getCmsContent('SafeliteShopNameWidget', 'Text');
|
||||
return this.getCmsContent('SafeliteShopNameWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
}
|
||||
return toTitleCase(this.modelValue.companyName);
|
||||
},
|
||||
modalHeaderText() {
|
||||
return this.getCmsContent(this.modalWidgetName, 'HeaderText').replaceAll('{custom:serviceZipcode}', this.internalZipcode);
|
||||
return this.getCmsContent(this.modalWidgetName, widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT).replaceAll('{custom:serviceZipcode}', this.internalZipcode);
|
||||
},
|
||||
modalFooterText() {
|
||||
return this.getCmsContent(this.modalWidgetName, 'FooterText');
|
||||
return this.getCmsContent(this.modalWidgetName, widgetFields.CONTENT_GROUP_WIDGET.FOOTER_TEXT);
|
||||
},
|
||||
modalName() {
|
||||
return this.modalWidgetName;
|
||||
|
|
@ -162,7 +175,7 @@ export default {
|
|||
};
|
||||
},
|
||||
serviceZipPrompt() {
|
||||
return this.getCmsContent(this.modalWidgetName, 'BodyText2');
|
||||
return this.getCmsContent(this.modalWidgetName, widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2);
|
||||
},
|
||||
nearbyShopsData() {
|
||||
return this.nearbyShops.map((shopProvider) => {
|
||||
|
|
@ -179,11 +192,22 @@ export default {
|
|||
value: shopProvider.providerNumber
|
||||
};
|
||||
});
|
||||
},
|
||||
searchRadiusOptions() {
|
||||
const options = this.getCmsContent(this.searchRadiusQuestionWidgetName, widgetFields.INPUT_QUESTION_WIDGET.ANSWERS);
|
||||
const optionsObj = {};
|
||||
options.forEach(option => {
|
||||
optionsObj[option.Name] = option.Text;
|
||||
});
|
||||
return optionsObj;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
internalZipcode() {
|
||||
this.resetsOnZipInput();
|
||||
this.refreshShops();
|
||||
},
|
||||
async searchRadiusInMiles() {
|
||||
this.nearbyShops = await this.getNearbyShops(this.searchRadiusInMiles);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -200,11 +224,9 @@ export default {
|
|||
closeModal() {
|
||||
this.$refs[this.modalName].closeModal();
|
||||
},
|
||||
onInputIdAssigned(inputId) {
|
||||
this.serviceZipCodeTextInputId = inputId;
|
||||
},
|
||||
onModalOpened() {
|
||||
this.internalZipcode = this.serviceZipcode;
|
||||
this.searchRadiusInMiles = 25;
|
||||
this.resetsOnZipInput().then(() => {
|
||||
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
import { buttonVariants } from '@/constants/component-variants';
|
||||
import buttonSizes from '@/constants/button-sizes';
|
||||
|
||||
/** @ignore */
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
import { buttonVariants } from '@/constants/component-variants';
|
||||
import buttonSizes from '@/constants/button-sizes';
|
||||
|
||||
export default {
|
||||
|
|
|
|||
Loading…
Reference in a new issue