Merge pull request #2536 from Safelite/rlsmerge/2025.05.22-to-develop
Rlsmerge/2025.05.22 to develop
This commit is contained in:
commit
cc9e554591
12 changed files with 85 additions and 50 deletions
|
|
@ -859,7 +859,7 @@ export default {
|
|||
}
|
||||
.calendar-grid-container {
|
||||
margin: 0 auto 1rem auto;
|
||||
max-width: 400px;
|
||||
max-width: 360px;
|
||||
position: relative;
|
||||
transition:
|
||||
height ease 2s,
|
||||
|
|
@ -869,9 +869,6 @@ export default {
|
|||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0;
|
||||
@include media-breakpoint-up(md) {
|
||||
padding: 0 0.75rem;
|
||||
}
|
||||
opacity: 1;
|
||||
|
||||
.grid-item {
|
||||
|
|
@ -1004,6 +1001,7 @@ export default {
|
|||
min-width: 2.5rem;
|
||||
width: 2.5rem;
|
||||
height: 2.5rem;
|
||||
border: 2px solid transparent;
|
||||
|
||||
span {
|
||||
&.small {
|
||||
|
|
|
|||
|
|
@ -452,12 +452,6 @@ export default {
|
|||
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() {
|
||||
this.unloadAutocomplete();
|
||||
},
|
||||
|
|
|
|||
|
|
@ -235,9 +235,11 @@ export default {
|
|||
this.displayMismatchStateAndZipAlert = false;
|
||||
},
|
||||
async setMobileLocation() {
|
||||
this.resetAlerts();
|
||||
// Validate the Zip Code
|
||||
if (this.internalModel.addressQuestions.zipCode === "") {
|
||||
if (
|
||||
this.internalModel.addressQuestions.zipCode === "" ||
|
||||
this.internalModel.addressQuestions.zipCode.length !== 5
|
||||
) {
|
||||
this.setMobileLocationInvalid(true);
|
||||
return;
|
||||
}
|
||||
|
|
@ -247,10 +249,12 @@ export default {
|
|||
);
|
||||
|
||||
if (!zipCodeData.isValid) {
|
||||
this.displayMismatchStateAndZipAlert = false;
|
||||
this.displayInvalidZipAlert = true;
|
||||
this.setMobileLocationInvalid(true);
|
||||
return;
|
||||
} else if (zipCodeData.state != this.internalModel.addressQuestions.state) {
|
||||
this.displayInvalidZipAlert = false;
|
||||
this.displayMismatchStateAndZipAlert = true;
|
||||
this.setMobileLocationInvalid(true);
|
||||
return;
|
||||
|
|
@ -258,6 +262,9 @@ export default {
|
|||
this.internalModel.addressQuestions.zipCode !==
|
||||
this.modelValue.addressQuestions.zipCode
|
||||
) {
|
||||
//reset alerts
|
||||
this.resetAlerts();
|
||||
|
||||
// retrieve mobile fee part
|
||||
const serviceZipCode = this.internalModel.addressQuestions.zipCode;
|
||||
const mobileFeePart = await getPricedMobileFeePart(
|
||||
|
|
@ -292,7 +299,6 @@ export default {
|
|||
}
|
||||
// update the page level model
|
||||
this.$emit("setMobileLocation", this.internalModel);
|
||||
this.setMobileLocationInvalid(false);
|
||||
},
|
||||
toggleMobileLocation() {
|
||||
this.isMobileLocationOpened = !this.isMobileLocationOpened;
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.modal-dialog {
|
||||
.mobile-location-questions {
|
||||
.question-text {
|
||||
& > span {
|
||||
text-align: left;
|
||||
|
|
|
|||
|
|
@ -355,6 +355,7 @@ describe("service-location.vue", () => {
|
|||
zipCode: "61606",
|
||||
},
|
||||
isVehicleProtected: null,
|
||||
isMobileSelected: false,
|
||||
};
|
||||
|
||||
// Act
|
||||
|
|
@ -468,6 +469,7 @@ describe("service-location.vue", () => {
|
|||
zipCode: "43054",
|
||||
},
|
||||
isVehicleProtected: true,
|
||||
isMobileSelected: false,
|
||||
};
|
||||
|
||||
//wrapper.vm.closeModalAction = jest.fn();
|
||||
|
|
|
|||
|
|
@ -175,12 +175,12 @@ const MOBILE_FEE_PART_TYPE = "MOBILE FEE";
|
|||
// DEFINE VALIDATION RULES
|
||||
defineRule("mobile-location-required", (value) => {
|
||||
if (
|
||||
value.isMobileSelected &&
|
||||
(!value.addressQuestions.streetAddress ||
|
||||
!value.addressQuestions.city ||
|
||||
!value.addressQuestions.state ||
|
||||
!value.addressQuestions.zipCode ||
|
||||
!value.isVehicleProtected) &&
|
||||
value.isMobileSelected
|
||||
!value.isVehicleProtected)
|
||||
) {
|
||||
return errorMessages.MOBILE_LOCATION_REQUIRED;
|
||||
}
|
||||
|
|
@ -305,6 +305,9 @@ export default {
|
|||
zipCode: this.zipCode,
|
||||
},
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
isMobileSelected:
|
||||
this.selectedAppointmentType == AppointmentTypeStrings.MOBILE &&
|
||||
!this.getIsMobileLocationOpened(),
|
||||
};
|
||||
},
|
||||
},
|
||||
|
|
@ -523,6 +526,7 @@ export default {
|
|||
}
|
||||
if (this.isServiceableMobile) {
|
||||
this.setMobileLocation(newValue);
|
||||
this.setMobileLocationInValid(false);
|
||||
} else {
|
||||
await getZipCodeData(newZipCode).then((zipCodeData) => {
|
||||
this.serviceZipCodeQuestion = {
|
||||
|
|
@ -756,11 +760,16 @@ export default {
|
|||
},
|
||||
displayMobileAddressQuestion(openMobileLocation) {
|
||||
var mobileLocationQuestionsRef = this.$refs.mobileLocationQuestions;
|
||||
var isMobileAddressComplete = mobileLocationQuestionsRef.isMobileAddressComplete;
|
||||
if (isMobileAddressComplete) {
|
||||
var isMobileAddressComplete = mobileLocationQuestionsRef?.isMobileAddressComplete;
|
||||
if (isMobileAddressComplete?.()) {
|
||||
mobileLocationQuestionsRef.isMobileLocationOpened = false;
|
||||
} else {
|
||||
mobileLocationQuestionsRef.isMobileLocationOpened = openMobileLocation;
|
||||
}
|
||||
},
|
||||
getIsMobileLocationOpened() {
|
||||
return this.$refs.mobileLocationQuestions?.isMobileLocationOpened;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
zipCode: {
|
||||
|
|
@ -772,10 +781,8 @@ export default {
|
|||
this.selectedProvider = new Provider(
|
||||
this.shopProviderData.mobileProviderNumber
|
||||
);
|
||||
this.displayMobileAddressQuestion(true);
|
||||
} else {
|
||||
this.selectedProvider = new Provider();
|
||||
this.displayMobileAddressQuestion(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -225,6 +225,15 @@ export default {
|
|||
|
||||
return index;
|
||||
},
|
||||
async handleUpdate(selectedShopIndex = null) {
|
||||
this.resetAnswers();
|
||||
if (selectedShopIndex >= 3) {
|
||||
await this.getNextShopsFromList(selectedShopIndex + 1);
|
||||
} else {
|
||||
await this.getNextShopsFromList();
|
||||
await nextTick();
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
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
|
||||
// up the component initialization on page load.
|
||||
async handler() {
|
||||
await nextTick();
|
||||
this.resetAnswers();
|
||||
this.getNextShopsFromList();
|
||||
this.handleUpdate();
|
||||
},
|
||||
},
|
||||
shopProviders: {
|
||||
async handler(newValue) {
|
||||
this.resetAnswers();
|
||||
|
||||
await nextTick();
|
||||
const selectedShopIndex = this.getSelectedProviderIndex(
|
||||
newValue,
|
||||
this.selectedProviderNumber
|
||||
);
|
||||
|
||||
if (selectedShopIndex >= 3) {
|
||||
await this.getNextShopsFromList(selectedShopIndex + 1);
|
||||
} else {
|
||||
await this.getNextShopsFromList();
|
||||
await nextTick();
|
||||
}
|
||||
this.handleUpdate(selectedShopIndex);
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -646,6 +646,9 @@ describe("vehicle-damage.vue", () => {
|
|||
isRepair: null,
|
||||
numberOfChips: null,
|
||||
},
|
||||
externalParameterState: {
|
||||
isExternalParameter: false,
|
||||
},
|
||||
};
|
||||
|
||||
var windshieldSelections = wrapper.vm.getWindshieldOptionsFromStore();
|
||||
|
|
|
|||
|
|
@ -148,6 +148,13 @@ export default {
|
|||
if (store.getters.externalParameterState?.isExternalParameter) {
|
||||
await nextTick();
|
||||
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) {
|
||||
vm.forwardButtonAction();
|
||||
} else {
|
||||
|
|
@ -176,6 +183,21 @@ export default {
|
|||
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();
|
||||
}
|
||||
} else {
|
||||
|
|
@ -322,9 +344,11 @@ export default {
|
|||
) {
|
||||
windShieldOptions.selectedWindshieldDamageType =
|
||||
damageLocationsSelected.REPLACE;
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.SINGLE
|
||||
);
|
||||
if (!store.getters.externalParameterState.isExternalParameter) {
|
||||
windShieldOptions.selectedWindshieldReplaceOptions.push(
|
||||
damageLocationsSelected.SINGLE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -532,6 +532,9 @@ export default {
|
|||
|
||||
if (!closestShops || closestShops.data?.providers?.length === 0) {
|
||||
this.displayNoServiceAlert = true;
|
||||
if (store.getters.externalParameterState?.isExternalParameter) {
|
||||
return baseMixin.methods.ResetExternalParamsAndHideModal();
|
||||
}
|
||||
return this.$refs.navbar.removeLoader();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -312,15 +312,7 @@ export default {
|
|||
}
|
||||
|
||||
// Cash Quote or Cash Price Sub Total
|
||||
if (isPricingAvailable) {
|
||||
const subtotal = baseMixin.methods
|
||||
.getTotalPriceOfAllLineItemsAndChildParts(combinedLineItems, false)
|
||||
.toFixed(2);
|
||||
|
||||
payload.cashPriceSubTotal = parseFloat(subtotal);
|
||||
} else {
|
||||
payload.cashPriceSubTotal = "";
|
||||
}
|
||||
payload.cashPriceSubTotal = store.getters.order?.cashPriceSubTotal ?? "";
|
||||
|
||||
//unverified (in scenarios we don’t display the price)
|
||||
if (
|
||||
|
|
|
|||
|
|
@ -3629,25 +3629,25 @@ export function mapTaxedLineItemsToStoreFormat(availableLineItems, storeLineItem
|
|||
export function getArrayOfAllLineItemsAndChildParts(lineItems) {
|
||||
let consolidatedLineItemsArray = [];
|
||||
|
||||
if (lineItems.glassParts != null)
|
||||
if (lineItems?.glassParts != null)
|
||||
consolidatedLineItemsArray = [
|
||||
...consolidatedLineItemsArray,
|
||||
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.glassParts),
|
||||
];
|
||||
|
||||
if (lineItems.supportingItems != null)
|
||||
if (lineItems?.supportingItems != null)
|
||||
consolidatedLineItemsArray = [
|
||||
...consolidatedLineItemsArray,
|
||||
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.supportingItems),
|
||||
];
|
||||
|
||||
if (lineItems.vaps != null)
|
||||
if (lineItems?.vaps != null)
|
||||
consolidatedLineItemsArray = [
|
||||
...consolidatedLineItemsArray,
|
||||
...getFlattenedArrayOfLineItemsWithChildParts(lineItems.vaps),
|
||||
];
|
||||
|
||||
if (lineItems.promos != null)
|
||||
if (lineItems?.promos != null)
|
||||
consolidatedLineItemsArray = [
|
||||
...consolidatedLineItemsArray,
|
||||
...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 date not in past, then call schedule service to verify appointment is still available.
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue