Merge pull request #2403 from Safelite/rlsmerge/heavy.truck-to-04.24

Rlsmerge/heavy.truck to 04.24
This commit is contained in:
CarlNation 2025-04-08 10:52:26 -04:00 committed by GitHub
commit d509215643
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 216 additions and 12 deletions

View file

@ -192,6 +192,10 @@ const endpoints = {
url: "/account/api/v1/account/bill-to-account-number",
method: "GET",
},
ClosestApplicableShops: {
url: "/location/api/v1/location/closest-applicable-shops",
method: "GET",
},
AddDonationPart: {
url: "/order/api/v1/order/add-donation-part",
method: "POST",

View file

@ -55,6 +55,7 @@ const storeActions = {
GET_INSURANCE_COMPANY_LIST: "getInsuranceCompanyList",
GET_BILL_TO_ACCOUNT_NUMBER: "getBillToAccountNumber",
GET_RECAL_PARTS_AND_SAVE_TO_LINE_ITEMS: "getRecalPartsAndSaveToLineItems",
GET_CLOSEST_APPLICABLE_SHOPS: "getClosestApplicableShops",
// Analytics
LOG_EXPERIMENT_EXPOSURE_AND_UPDATE_STORE: "logExperimentExposureAndUpdateStore",

View file

@ -9,6 +9,9 @@ const storeMutations = {
UPDATE_MAKE: "updateMake",
UPDATE_MODEL: "updateModel",
UPDATE_STYLE: "updateStyle",
UPDATE_VEHICLE_SUBTYPE: "updateVehicleSubType",
UPDATE_VEHICLE_SPECIAL_CLASS: "updateVehicleSpecialClass",
UPDATE_IS_BIGTRUCK: "updateIsBigTruck",
UPDATE_CAR_ID: "updateCarId",
UPDATE_VEHICLE_CATEGORY: "updateVehicleCategory",
UPDATE_VEHICLE_IMAGE_URL: "updateVehicleImageUrl",
@ -16,6 +19,7 @@ const storeMutations = {
UPDATE_VEHICLE_IMAGE_COLOR: "updateVehicleImageColor",
UPDATE_VEHICLE_VIN: "updateVehicleVin",
UPDATE_VEHICLE: "updateVehicle",
UPDATE_VEHICLE_CAN_SAFELITE_SERVICE: "updateVehicleCanSafeliteService",
UPDATE_IS_REPAIR: "updateIsRepair",
UPDATE_NUMBER_OF_CHIPS: "updateNumberOfChips",

View file

@ -149,6 +149,23 @@ export async function getAvailabilityRating(
return shopStatus;
}
export async function getClosestApplicableShops(serviceZipCode, carId, pageNameToLog) {
if (!serviceZipCode) {
return null;
}
const closestShops = await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_CLOSEST_APPLICABLE_SHOPS,
{
zip: serviceZipCode,
carId: carId,
},
pageNameToLog
);
return closestShops.data;
}
export async function getZipCodeData(serviceZipCode) {
return await baseMixin.methods.getZipCodeData(serviceZipCode, "service-location");
}

View file

@ -15,6 +15,8 @@
editScreenReaderTextCmsWidgetName="ScreenReaderZipEditWidget"
v-model="serviceZipCodeQuestion"
ref="serviceZipCodeQuestion"
:carId="carId"
:isVehicleHeavyTruck="isVehicleHeavyTruck"
:mobileFeePart="mobileFeePart"
@updated-mobile-fee-part="setMobileFeePart"
@updated-recycle-fee-part="setRecycleFeePart"
@ -186,9 +188,11 @@ export default {
return {
streetAddress: this.getServiceAddressFromStore(),
apartmentNumberOrBusinessName: this.getServiceAddress2FromStore(),
carId: this.getCarIdfromStore(),
city: this.getServiceCityFromStore(),
state: this.getServiceStateFromStore(),
zipCode: this.getServiceZipCodeFromStore(),
isVehicleHeavyTruck: this.getIsVehicleHeavyTruckFromStore(),
isVehicleProtected: this.getIsVehicleProtectedFromStore(),
isGlassServiceableInshop: null,
isRecalibrationServiceableInshop: null,
@ -514,6 +518,9 @@ export default {
});
}
},
getCarIdfromStore() {
return store.getters.vehicle.carId;
},
getServiceAddressFromStore() {
return store.getters.order.serviceLocation.address;
},
@ -529,6 +536,9 @@ export default {
getServiceZipCodeFromStore() {
return store.getters.order.serviceLocation.zipCode;
},
getIsVehicleHeavyTruckFromStore() {
return store.getters.order.vehicle?.isBigTruck ?? false;
},
getIsVehicleProtectedFromStore() {
return store.getters.order.serviceLocation.isVehicleProtected;
},

View file

@ -33,6 +33,13 @@
cmsWidgetName="AlertInvalidZipWidget"
alertClass="alert-danger"
v-bind:isDismissible="false" />
<alert
ref="AlertNoService"
v-if="displayNoServiceAlert"
class="my-4"
cmsWidgetName="AlertNoServiceWidget"
alertClass="alert-danger"
v-bind:isDismissible="false" />
</modal>
</template>
@ -48,6 +55,7 @@ import {
getPricedRecycleFeePart,
getServiceabilityDetails,
getBillToAccountNumber,
getClosestApplicableShops,
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
export default {
@ -63,6 +71,7 @@ export default {
internalModel: this.copyModel(this.modelValue),
serviceZipCodeTextInputId: "",
displayInvalidZipAlert: false,
displayNoServiceAlert: false,
};
},
props: {
@ -73,6 +82,11 @@ export default {
zipCode: "",
}),
},
carId: String,
isVehicleHeavyTruck: {
type: Boolean,
default: false,
},
mobileFeePart: {
type: Object,
default: () => ({}),
@ -107,6 +121,7 @@ export default {
methods: {
resetAlerts() {
this.displayInvalidZipAlert = false;
this.displayNoServiceAlert = false;
},
resetsOnZipInput() {
this.resetAlerts();
@ -155,6 +170,22 @@ export default {
this.focusOnZipInput();
this.resetModalButtonStyle();
} else {
if (this.isVehicleHeavyTruck) {
// check the location endpoint to verify this zip can service a heavy truck
const closestShops = await getClosestApplicableShops(
this.internalModel.zipCode,
this.carId,
"service-location"
);
if (!closestShops || closestShops.providers?.length === 0) {
this.displayNoServiceAlert = true;
this.focusOnZipInput();
this.resetModalButtonStyle();
return null;
}
}
this.internalModel.state = zipCodeData.state;
this.internalModel.zipCodeCtu = zipCodeData.zipCodeCtu;

View file

@ -179,12 +179,12 @@ export default {
}
});
this.pushEventToGA(
this.GaCategories.SERVICE_LOCATION,
gaAction,
shops.join(","),
true
);
var joinedShops = shops.join(",");
if (!joinedShops) {
joinedShops = "no-shops";
}
this.pushEventToGA(this.GaCategories.SERVICE_LOCATION, gaAction, joinedShops, true);
}
if (this.answers.length === 0) {

View file

@ -48,6 +48,19 @@
validationRules="style-required"
placeHolderText="Select style"
customDropdownId="styleQuestionField" />
<div v-if="isBigTruckAndCanService">
<div class="separator-line"></div>
<textboxQuestion
class="mb-4"
cmsWidgetName="ServiceZipQuestionWidget"
v-model="serviceZipCode"
inputId="serviceZipCode"
mask="#####"
isRequired
validationRules="zip-required|zip-format" />
</div>
<alert
ref="AlertNoService"
v-if="displayNoServiceAlert"
@ -76,6 +89,7 @@ import navbar from "@/fmg-components/nav-bar/nav-bar";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
import alert from "@/ux-components/alert/alert";
import vehicleQuestion from "@/layouts/vehicle/vehicle-question/vehicle-question";
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
// Supporting files
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
@ -87,7 +101,7 @@ import {
} from "@/helpers/heritage-integration/cookie-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import { Form, defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules";
import { required, regex } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
@ -102,6 +116,8 @@ defineRule("year-required", required(errorMessages.YEAR_REQUIRED));
defineRule("make-required", required(errorMessages.MAKE_REQUIRED));
defineRule("model-required", required(errorMessages.MODEL_REQUIRED));
defineRule("style-required", required(errorMessages.STYLE_REQUIRED));
defineRule("zip-required", required(errorMessages.ZIP_REQUIRED));
defineRule("zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.ZIP_FORMAT));
export default {
name: "vehicle",
@ -113,23 +129,29 @@ export default {
selectedStyle: this.selectedStylefromStore(),
carId: this.getCarIdfromStore(),
category: this.getCategoryfromStore(),
isBigTruck: this.getIsBigTruckfromStore(),
imageUrl: this.getImagefromStore(),
imageVifNumber: this.getImageVifNumberfromStore(),
imageVifColor: this.getImageVifColorfromStore(),
serviceZipCode: this.getZipFromStore() ?? this.$route.query.zipcode,
yearOptions: [],
makeOptions: [],
modelOptions: [],
styleOptions: [],
displayNoServiceAlert: false,
canSafeliteService: this.canSafeliteServiceFromStore(),
};
},
async beforeRouteEnter(to, from, next) {
const log = getQuerystringParameter(queryStrings.LOG);
if (log === "true") {
console.log("----------------- applicationConfig start -----------------");
if (store.getters.applicationUser.loggingOption) {
console.log(
new Date() + "------------- vehicle.vue applicationConfig start -------------"
);
console.log(new Date() + JSON.stringify(applicationConfig));
console.log("----------------- applicationConfig end -----------------");
console.log(
new Date() + "------------- vehicle.vue applicationConfig end -------------"
);
}
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
@ -293,12 +315,17 @@ export default {
},
watch: {
serviceZipCode(newValue, oldValue) {
this.resetAlert();
},
async selectedYear(year) {
this.resetAlert();
this.makeOptions = [];
this.selectedMake = null;
this.selectedModel = null;
this.selectedStyle = null;
this.isBigTruck = false;
this.canSafeliteService = false;
this.carId = null;
if (year) {
const result = await this.getMakeOptions(year);
@ -318,6 +345,7 @@ export default {
this.modelOptions = [];
this.selectedModel = null;
this.selectedStyle = null;
this.isBigTruck = null;
this.carId = null;
if (make) {
const result = await this.getModelOptions(this.selectedYear, make);
@ -336,6 +364,7 @@ export default {
this.resetAlert();
this.styleOptions = [];
this.selectedStyle = null;
this.isBigTruck = false;
this.carId = null;
if (model) {
const result = await this.getStyleOptions(
@ -400,8 +429,17 @@ export default {
!!this.carId
);
},
isBigTruckAndCanService() {
return this.isBigTruck && this.canSafeliteService;
},
},
methods: {
getZipFromStore() {
return (
store.getters?.externalParameterServiceZip?.zipCode ??
store.getters.order?.serviceLocation?.zipCode
);
},
isDisabled(options) {
if (
!options.length ||
@ -443,6 +481,10 @@ export default {
this.imageVifNumber = result?.data.imageVifNumber;
this.imageVifColor = result?.data.imageVifColor;
this.displayNoServiceAlert = !result?.data.canSafeliteService;
this.canSafeliteService = result?.data.canSafeliteService;
this.vehicleSubType = result?.data.vehicleSubType;
this.vehicleSpecialClass = result?.data.vehicleSpecialClass;
this.isBigTruck = result?.data.isBigTruck;
},
resetAlert() {
this.displayNoServiceAlert = false;
@ -456,14 +498,44 @@ export default {
make: this.selectedMake,
model: this.selectedModel,
style: this.selectedStyle,
vehicleSubType: this.vehicleSubType,
vehicleSpecialClass: this.vehicleSpecialClass,
isBigTruck: this.isBigTruck,
carId: this.carId,
category: this.category,
canSafeliteService: this.canSafeliteService,
imageUrl: this.imageUrl,
imageVifNumber: this.imageVifNumber,
imageVifColor: this.imageVifColor,
},
false
);
if (this.isBigTruck) {
const zipCodeData = await this.getZipCodeData(this.serviceZipCode);
await this.dispatchStoreAction(
storeActions.SAVE_SERVICE_ZIP_CODE_INFO,
{
zipCode: this.serviceZipCode,
state: zipCodeData.state,
zipCodeCtu: zipCodeData.zipCodeCtu,
},
false
);
// check the location endpoint to verify this zip can service a heavy truck
var closestShops = await this.dispatchStoreActionWithLogging(
storeActions.GET_CLOSEST_APPLICABLE_SHOPS,
{ zip: this.serviceZipCode, carId: this.carId },
"vehicle"
);
if (!closestShops || closestShops.data?.providers?.length === 0) {
this.displayNoServiceAlert = true;
return this.$refs.navbar.removeLoader();
}
}
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
},
initializeYearComponent(initialData) {
@ -489,6 +561,9 @@ export default {
selectedStylefromStore() {
return store.getters.externalParameterVehicle.style ?? store.getters.vehicle.style;
},
canSafeliteServiceFromStore() {
return store.getters.vehicle.canSafeliteService ?? false;
},
async getMakeOptions(year) {
return await baseMixin.methods.dispatchStoreActionWithLogging(
storeActions.GET_VEHICLE_MAKES,
@ -536,6 +611,9 @@ export default {
getImageVifColorfromStore() {
return store.getters.vehicle.imageVifColor;
},
getIsBigTruckfromStore() {
return store.getters.vehicle.isBigTruck;
},
},
components: {
@ -545,6 +623,7 @@ export default {
Form,
alert,
vehicleQuestion,
textboxQuestion,
},
};
</script>
@ -557,4 +636,9 @@ export default {
margin-top: 1.5rem;
margin-bottom: 0;
}
.separator-line {
grid-area: 2/1/2/8;
border-top: 1px solid $gray-500;
margin: 0.5rem 0;
}
</style>

View file

@ -66,9 +66,13 @@ const getDefaultState = () => {
make: null,
model: null,
style: null,
vehicleSubType: null,
vehicleSpecialClass: null,
isBigTruck: false,
carId: null,
category: null,
vin: null,
canSafeliteService: null,
imageUrl: null,
imageVifNumber: null,
imageColor: null,
@ -216,12 +220,24 @@ export const mutations = {
updateStyle(state, style) {
state.order.vehicle.style = style;
},
updateVehicleSubType(state, vehicleSubType) {
state.order.vehicle.vehicleSubType = vehicleSubType;
},
updateVehicleSpecialClass(state, vehicleSpecialClass) {
state.order.vehicle.vehicleSpecialClass = vehicleSpecialClass;
},
updateIsBigTruck(state, isBigTruck) {
state.order.vehicle.isBigTruck = isBigTruck;
},
updateCarId(state, carId) {
state.order.vehicle.carId = carId;
},
updateVehicleCategory(state, category) {
state.order.vehicle.category = category;
},
updateVehicleCanSafeliteService(state, canSafeliteService) {
state.order.vehicle.canSafeliteService = canSafeliteService;
},
updateVehicleImageUrl(state, imageUrl) {
state.order.vehicle.imageUrl = imageUrl;
},
@ -1248,6 +1264,15 @@ export const actions = {
});
},
getClosestApplicableShops(context, { payload: { zip, carId }, pageNameToLog }) {
return globalMethods.callHttpClient({
methods: endpoints.ClosestApplicableShops.method,
endpoint: `${endpoints.ClosestApplicableShops.url}/${zip}/${carId}`,
logApiCall: true,
pageNameToLog: pageNameToLog,
});
},
// Dependency Actions
resetVehicleStateAndDependencies(context) {
context.commit(storeMutations.RESET_VEHICLE_STATE);
@ -1835,6 +1860,8 @@ export const actions = {
endPoint += `&${glassPieces}`;
}
endPoint += `&isHeavyTruckVehicle=${context.getters.order.vehicle.isBigTruck}`;
return globalMethods.callHttpClient({
method: endpoints.GetServiceabilityDetails.method,
endpoint: endPoint,
@ -1861,6 +1888,8 @@ export const actions = {
if (windshieldPartWithRecal) {
url += `/${windshieldPartWithRecal.partNumber}`;
}
//heavy truck vehicle
url += `/${context.getters.order.vehicle.isBigTruck}`;
return globalMethods.callHttpClient({
method: endpoints.GetProviders.method,
@ -2135,6 +2164,9 @@ export const actions = {
year: vehicle.year,
make: vehicle.make,
model: vehicle.model,
subType: vehicle.vehicleSubType,
specialClass: vehicle.vehicleSpecialClass,
isBigTruck: vehicle.isBigTruck,
isInsurance: order.payment.isInsurance ?? false,
isVerified: order.payment.insuranceCoverage.isVerified ?? false,
lineItems: {
@ -2188,6 +2220,9 @@ export const actions = {
model: vehicle.model,
style: vehicle.style,
vin: vehicle.vin,
vehicleSubType: vehicle.vehicleSubType,
vehicleSpecialClass: vehicle.vehicleSpecialClass,
isBigTruck: vehicle.isBigTruck,
registration: {
firstName: vehicle.registration.firstName,
lastName: vehicle.registration.lastName,
@ -2398,7 +2433,21 @@ export const actions = {
// Vehicle
saveVehicle(
context,
{ year, make, model, style, carId, category, imageUrl, imageVifNumber, imageVifColor }
{
year,
make,
model,
style,
vehicleSubType,
vehicleSpecialClass,
isBigTruck,
carId,
category,
canSafeliteService,
imageUrl,
imageVifNumber,
imageVifColor,
}
) {
if (
context.state.order.vehicle.year != year ||
@ -2414,8 +2463,12 @@ export const actions = {
context.commit(storeMutations.UPDATE_MAKE, make);
context.commit(storeMutations.UPDATE_MODEL, model);
context.commit(storeMutations.UPDATE_STYLE, style);
context.commit(storeMutations.UPDATE_VEHICLE_SUBTYPE, vehicleSubType);
context.commit(storeMutations.UPDATE_VEHICLE_SPECIAL_CLASS, vehicleSpecialClass);
context.commit(storeMutations.UPDATE_IS_BIGTRUCK, isBigTruck);
context.commit(storeMutations.UPDATE_CAR_ID, carId);
context.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, category);
context.commit(storeMutations.UPDATE_VEHICLE_CAN_SAFELITE_SERVICE, canSafeliteService);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_URL, imageUrl);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_VIF_NUMBER, imageVifNumber);
context.commit(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, imageVifColor);