Merge branch 'release/2025.05.22' into rlsmerge/2025.05.22-to-develop

This commit is contained in:
CarlNation 2025-05-19 14:24:30 -04:00
commit 77c67b7a44
12 changed files with 85 additions and 50 deletions

View file

@ -859,7 +859,7 @@ export default {
} }
.calendar-grid-container { .calendar-grid-container {
margin: 0 auto 1rem auto; margin: 0 auto 1rem auto;
max-width: 400px; max-width: 360px;
position: relative; position: relative;
transition: transition:
height ease 2s, height ease 2s,
@ -869,9 +869,6 @@ export default {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
padding: 0; padding: 0;
@include media-breakpoint-up(md) {
padding: 0 0.75rem;
}
opacity: 1; opacity: 1;
.grid-item { .grid-item {
@ -1004,6 +1001,7 @@ export default {
min-width: 2.5rem; min-width: 2.5rem;
width: 2.5rem; width: 2.5rem;
height: 2.5rem; height: 2.5rem;
border: 2px solid transparent;
span { span {
&.small { &.small {

View file

@ -452,12 +452,6 @@ export default {
this.loadGooglePlacesAutocompleteScript(); this.loadGooglePlacesAutocompleteScript();
} }
}, },
beforeUpdate() {
// It is necessary to set focus on the street address on this lifecycle hook when this component is used in a modal.
if (!this.addressField1.matches(":focus")) {
this.addressField1.focus();
}
},
unmounted() { unmounted() {
this.unloadAutocomplete(); this.unloadAutocomplete();
}, },

View file

@ -235,9 +235,11 @@ export default {
this.displayMismatchStateAndZipAlert = false; this.displayMismatchStateAndZipAlert = false;
}, },
async setMobileLocation() { async setMobileLocation() {
this.resetAlerts();
// Validate the Zip Code // Validate the Zip Code
if (this.internalModel.addressQuestions.zipCode === "") { if (
this.internalModel.addressQuestions.zipCode === "" ||
this.internalModel.addressQuestions.zipCode.length !== 5
) {
this.setMobileLocationInvalid(true); this.setMobileLocationInvalid(true);
return; return;
} }
@ -247,10 +249,12 @@ export default {
); );
if (!zipCodeData.isValid) { if (!zipCodeData.isValid) {
this.displayMismatchStateAndZipAlert = false;
this.displayInvalidZipAlert = true; this.displayInvalidZipAlert = true;
this.setMobileLocationInvalid(true); this.setMobileLocationInvalid(true);
return; return;
} else if (zipCodeData.state != this.internalModel.addressQuestions.state) { } else if (zipCodeData.state != this.internalModel.addressQuestions.state) {
this.displayInvalidZipAlert = false;
this.displayMismatchStateAndZipAlert = true; this.displayMismatchStateAndZipAlert = true;
this.setMobileLocationInvalid(true); this.setMobileLocationInvalid(true);
return; return;
@ -258,6 +262,9 @@ export default {
this.internalModel.addressQuestions.zipCode !== this.internalModel.addressQuestions.zipCode !==
this.modelValue.addressQuestions.zipCode this.modelValue.addressQuestions.zipCode
) { ) {
//reset alerts
this.resetAlerts();
// retrieve mobile fee part // retrieve mobile fee part
const serviceZipCode = this.internalModel.addressQuestions.zipCode; const serviceZipCode = this.internalModel.addressQuestions.zipCode;
const mobileFeePart = await getPricedMobileFeePart( const mobileFeePart = await getPricedMobileFeePart(
@ -292,7 +299,6 @@ export default {
} }
// update the page level model // update the page level model
this.$emit("setMobileLocation", this.internalModel); this.$emit("setMobileLocation", this.internalModel);
this.setMobileLocationInvalid(false);
}, },
toggleMobileLocation() { toggleMobileLocation() {
this.isMobileLocationOpened = !this.isMobileLocationOpened; this.isMobileLocationOpened = !this.isMobileLocationOpened;

View file

@ -57,7 +57,7 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
.modal-dialog { .mobile-location-questions {
.question-text { .question-text {
& > span { & > span {
text-align: left; text-align: left;

View file

@ -355,6 +355,7 @@ describe("service-location.vue", () => {
zipCode: "61606", zipCode: "61606",
}, },
isVehicleProtected: null, isVehicleProtected: null,
isMobileSelected: false,
}; };
// Act // Act
@ -468,6 +469,7 @@ describe("service-location.vue", () => {
zipCode: "43054", zipCode: "43054",
}, },
isVehicleProtected: true, isVehicleProtected: true,
isMobileSelected: false,
}; };
//wrapper.vm.closeModalAction = jest.fn(); //wrapper.vm.closeModalAction = jest.fn();

View file

@ -175,12 +175,12 @@ const MOBILE_FEE_PART_TYPE = "MOBILE FEE";
// DEFINE VALIDATION RULES // DEFINE VALIDATION RULES
defineRule("mobile-location-required", (value) => { defineRule("mobile-location-required", (value) => {
if ( if (
value.isMobileSelected &&
(!value.addressQuestions.streetAddress || (!value.addressQuestions.streetAddress ||
!value.addressQuestions.city || !value.addressQuestions.city ||
!value.addressQuestions.state || !value.addressQuestions.state ||
!value.addressQuestions.zipCode || !value.addressQuestions.zipCode ||
!value.isVehicleProtected) && !value.isVehicleProtected)
value.isMobileSelected
) { ) {
return errorMessages.MOBILE_LOCATION_REQUIRED; return errorMessages.MOBILE_LOCATION_REQUIRED;
} }
@ -305,6 +305,9 @@ export default {
zipCode: this.zipCode, zipCode: this.zipCode,
}, },
isVehicleProtected: this.isVehicleProtected, isVehicleProtected: this.isVehicleProtected,
isMobileSelected:
this.selectedAppointmentType == AppointmentTypeStrings.MOBILE &&
!this.getIsMobileLocationOpened(),
}; };
}, },
}, },
@ -523,6 +526,7 @@ export default {
} }
if (this.isServiceableMobile) { if (this.isServiceableMobile) {
this.setMobileLocation(newValue); this.setMobileLocation(newValue);
this.setMobileLocationInValid(false);
} else { } else {
await getZipCodeData(newZipCode).then((zipCodeData) => { await getZipCodeData(newZipCode).then((zipCodeData) => {
this.serviceZipCodeQuestion = { this.serviceZipCodeQuestion = {
@ -756,11 +760,16 @@ export default {
}, },
displayMobileAddressQuestion(openMobileLocation) { displayMobileAddressQuestion(openMobileLocation) {
var mobileLocationQuestionsRef = this.$refs.mobileLocationQuestions; var mobileLocationQuestionsRef = this.$refs.mobileLocationQuestions;
var isMobileAddressComplete = mobileLocationQuestionsRef.isMobileAddressComplete; var isMobileAddressComplete = mobileLocationQuestionsRef?.isMobileAddressComplete;
if (isMobileAddressComplete) { if (isMobileAddressComplete?.()) {
mobileLocationQuestionsRef.isMobileLocationOpened = false;
} else {
mobileLocationQuestionsRef.isMobileLocationOpened = openMobileLocation; mobileLocationQuestionsRef.isMobileLocationOpened = openMobileLocation;
} }
}, },
getIsMobileLocationOpened() {
return this.$refs.mobileLocationQuestions?.isMobileLocationOpened;
},
}, },
watch: { watch: {
zipCode: { zipCode: {
@ -772,10 +781,8 @@ export default {
this.selectedProvider = new Provider( this.selectedProvider = new Provider(
this.shopProviderData.mobileProviderNumber this.shopProviderData.mobileProviderNumber
); );
this.displayMobileAddressQuestion(true);
} else { } else {
this.selectedProvider = new Provider(); this.selectedProvider = new Provider();
this.displayMobileAddressQuestion(false);
} }
}); });
} }

View file

@ -225,6 +225,15 @@ export default {
return index; return index;
}, },
async handleUpdate(selectedShopIndex = null) {
this.resetAnswers();
if (selectedShopIndex >= 3) {
await this.getNextShopsFromList(selectedShopIndex + 1);
} else {
await this.getNextShopsFromList();
await nextTick();
}
},
}, },
watch: { watch: {
selectedAppointmentType: { selectedAppointmentType: {
@ -233,27 +242,16 @@ export default {
// nothing to do with this component. We could mitigate this by showing / hiding this component with v-if but that messes // nothing to do with this component. We could mitigate this by showing / hiding this component with v-if but that messes
// up the component initialization on page load. // up the component initialization on page load.
async handler() { async handler() {
await nextTick(); this.handleUpdate();
this.resetAnswers();
this.getNextShopsFromList();
}, },
}, },
shopProviders: { shopProviders: {
async handler(newValue) { async handler(newValue) {
this.resetAnswers();
await nextTick();
const selectedShopIndex = this.getSelectedProviderIndex( const selectedShopIndex = this.getSelectedProviderIndex(
newValue, newValue,
this.selectedProviderNumber this.selectedProviderNumber
); );
this.handleUpdate(selectedShopIndex);
if (selectedShopIndex >= 3) {
await this.getNextShopsFromList(selectedShopIndex + 1);
} else {
await this.getNextShopsFromList();
await nextTick();
}
}, },
}, },
}, },

View file

@ -646,6 +646,9 @@ describe("vehicle-damage.vue", () => {
isRepair: null, isRepair: null,
numberOfChips: null, numberOfChips: null,
}, },
externalParameterState: {
isExternalParameter: false,
},
}; };
var windshieldSelections = wrapper.vm.getWindshieldOptionsFromStore(); var windshieldSelections = wrapper.vm.getWindshieldOptionsFromStore();

View file

@ -148,6 +148,13 @@ export default {
if (store.getters.externalParameterState?.isExternalParameter) { if (store.getters.externalParameterState?.isExternalParameter) {
await nextTick(); await nextTick();
const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm); const isValid = await baseMixin.methods.isFormValid(vm.$refs.theForm);
if (
store.getters.vehicle?.vehicleSubType === "MOTOR HOME" &&
store.getters.externalParameterDamage.damageType?.toUpperCase() ===
"WINDSHIELDREPLACE"
) {
return baseMixin.methods.ResetExternalParamsAndHideModal();
}
if (isValid) { if (isValid) {
vm.forwardButtonAction(); vm.forwardButtonAction();
} else { } else {
@ -176,6 +183,21 @@ export default {
false false
); );
} }
const selectedGlassToReplace =
resultMap.damageOptions.windshieldOptions.availableReplacementOptions;
if (selectedGlassToReplace == damageLocationsSelected.SINGLE) {
vm.selectedWindshieldOptions.selectedWindshieldReplaceOptions.push(
damageLocationsSelected.SINGLE
);
if (
store.getters.externalParameterState.isExternalParameter &&
store.getters.externalParameterDamage.damageType !== "other"
) {
return vm.forwardButtonAction();
}
}
baseMixin.methods.ResetExternalParamsAndHideModal(); baseMixin.methods.ResetExternalParamsAndHideModal();
} }
} else { } else {
@ -322,9 +344,11 @@ export default {
) { ) {
windShieldOptions.selectedWindshieldDamageType = windShieldOptions.selectedWindshieldDamageType =
damageLocationsSelected.REPLACE; damageLocationsSelected.REPLACE;
windShieldOptions.selectedWindshieldReplaceOptions.push( if (!store.getters.externalParameterState.isExternalParameter) {
damageLocationsSelected.SINGLE windShieldOptions.selectedWindshieldReplaceOptions.push(
); damageLocationsSelected.SINGLE
);
}
} }
if ( if (

View file

@ -532,6 +532,9 @@ export default {
if (!closestShops || closestShops.data?.providers?.length === 0) { if (!closestShops || closestShops.data?.providers?.length === 0) {
this.displayNoServiceAlert = true; this.displayNoServiceAlert = true;
if (store.getters.externalParameterState?.isExternalParameter) {
return baseMixin.methods.ResetExternalParamsAndHideModal();
}
return this.$refs.navbar.removeLoader(); return this.$refs.navbar.removeLoader();
} }
} }

View file

@ -312,15 +312,7 @@ export default {
} }
// Cash Quote or Cash Price Sub Total // Cash Quote or Cash Price Sub Total
if (isPricingAvailable) { payload.cashPriceSubTotal = store.getters.order?.cashPriceSubTotal ?? "";
const subtotal = baseMixin.methods
.getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, false)
.toFixed(2);
payload.cashPriceSubTotal = parseFloat(subtotal);
} else {
payload.cashPriceSubTotal = "";
}
//unverified (in scenarios we dont display the price) //unverified (in scenarios we dont display the price)
if ( if (

View file

@ -3629,25 +3629,25 @@ export function mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItem
export function getArrayOfAllLineItemsAndChildParts(lineItems) { export function getArrayOfAllLineItemsAndChildParts(lineItems) {
let consolidatedLineItemsArray = []; let consolidatedLineItemsArray = [];
if (lineItems.glassParts != null) if (lineItems?.glassParts != null)
consolidatedLineItemsArray = [ consolidatedLineItemsArray = [
...consolidatedLineItemsArray, ...consolidatedLineItemsArray,
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.glassParts), ...getFlattenedArrayOfLineItemsWithChildParts(lineItems.glassParts),
]; ];
if (lineItems.supportingItems != null) if (lineItems?.supportingItems != null)
consolidatedLineItemsArray = [ consolidatedLineItemsArray = [
...consolidatedLineItemsArray, ...consolidatedLineItemsArray,
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.supportingItems), ...getFlattenedArrayOfLineItemsWithChildParts(lineItems.supportingItems),
]; ];
if (lineItems.vaps != null) if (lineItems?.vaps != null)
consolidatedLineItemsArray = [ consolidatedLineItemsArray = [
...consolidatedLineItemsArray, ...consolidatedLineItemsArray,
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.vaps), ...getFlattenedArrayOfLineItemsWithChildParts(lineItems.vaps),
]; ];
if (lineItems.promos != null) if (lineItems?.promos != null)
consolidatedLineItemsArray = [ consolidatedLineItemsArray = [
...consolidatedLineItemsArray, ...consolidatedLineItemsArray,
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.promos), ...getFlattenedArrayOfLineItemsWithChildParts(lineItems.promos),
@ -3797,7 +3797,15 @@ function supportingItemsEqual(supportingItemsA, supportingItemsB) {
// if so, make sure it's not in the past. if in the past, clear schedule info in store. // if so, make sure it's not in the past. if in the past, clear schedule info in store.
// if date not in past, then call schedule service to verify appointment is still available. // if date not in past, then call schedule service to verify appointment is still available.
async function resetScheduleIfUnavailable(context, order, pageNameToLog) { async function resetScheduleIfUnavailable(context, order, pageNameToLog) {
if (!order.schedule?.date) { // lineItems empty can happen when a customer goes all the way through scheduling as cash but then
// switches to insurance AND also switches vehicles during policy lookup. If you call shop-time-slots
// without parts, you get 500 errors so skip the call.
const lineItems = getArrayOfAllLineItemsAndChildParts(order.lineItems);
if (!order.schedule?.date || lineItems.length === 0) {
console.log(new Date() + " no schedule date or lineItems. skip resetSchedule logic.");
console.log(new Date() + " schedule.schedule.date" + JSON.stringify(order.schedule));
console.log(new Date() + " lineItems" + JSON.stringify(order.lineItems));
return; return;
} }