Merge pull request #1285 from Safelite/feature/CSR-1418.2

Feature/csr 1418.2
This commit is contained in:
AMSNEHA 2023-08-02 17:34:27 +05:30 committed by GitHub
commit 7a9a0948d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 246 additions and 100 deletions

View file

@ -62,6 +62,7 @@ const storeActions = {
SAVE_VEHICLE_MAKE: "saveVehicleMake", SAVE_VEHICLE_MAKE: "saveVehicleMake",
SAVE_VEHICLE_MODEL: "saveVehicleModel", SAVE_VEHICLE_MODEL: "saveVehicleModel",
SAVE_VEHICLE_STYLE: "saveVehicleStyle", SAVE_VEHICLE_STYLE: "saveVehicleStyle",
SAVE_VEHICLE: "saveVehicle",
SAVE_VEHICLE_DAMAGE: "saveVehicleDamage", SAVE_VEHICLE_DAMAGE: "saveVehicleDamage",
SAVE_VIN_LOOKUP: "saveVinLookup", SAVE_VIN_LOOKUP: "saveVinLookup",
SAVE_SERVICE_ZIP_CODE_INFO: "saveServiceZipCodeInfo", SAVE_SERVICE_ZIP_CODE_INFO: "saveServiceZipCodeInfo",

View file

@ -16,9 +16,13 @@
:disabled="isDisabled" :disabled="isDisabled"
:aria-required="isRequired" :aria-required="isRequired"
:validationRules="validationRules" :validationRules="validationRules"
:placeHolderText="placeHolderText"> :placeHolderText="placeHolderText"
:valueAsKey="valueAsKey">
<option v-if="placeHolderText" value="" selected>{{ placeHolderText }}</option> <option v-if="placeHolderText" value="" selected>{{ placeHolderText }}</option>
<option v-for="(value, name, index) in options" :value="name" :key="index"> <option
v-for="(value, name, index) in options"
:value="valueAsKey == true ? value : name"
:key="valueAsKey == true ? value : index">
{{ value }} {{ value }}
</option> </option>
</select> </select>
@ -47,6 +51,11 @@ export default {
placeHolderText: String, placeHolderText: String,
cmsWidgetName: String, cmsWidgetName: String,
hasError: Boolean, hasError: Boolean,
valueAsKey: {
type: Boolean,
required: false,
default: false,
},
}, },
setup(props) { setup(props) {
const uuid = uuidv4(); const uuid = uuidv4();

View file

@ -1,9 +1,5 @@
<template> <template>
<dropdownQuestion <dropdownQuestion disableAutoFill v-model="selectedValue" :valueAsKey="true" />
:options="values"
disableAutoFill
v-model="selectedValue"
:isDisabled="!values.length" />
</template> </template>
<script> <script>
@ -12,16 +8,8 @@ import dropdownQuestion from "@/digital-components/dropdown-question/dropdown-qu
export default { export default {
name: "vehicle-question", name: "vehicle-question",
data() {
return {
values: [],
selectedIndex: null,
};
},
props: { props: {
modelValue: String, modelValue: String,
updateValues: Function,
}, },
components: { components: {
@ -30,33 +18,13 @@ export default {
computed: { computed: {
selectedValue: { selectedValue: {
get() { get: function () {
return this.selectedIndex?.toString(); return this.modelValue?.toString();
}, },
set(newValue) { set: function (newValue) {
this.selectedIndex = newValue;
newValue = newValue != null && newValue > -1 ? this.values[newValue] : null;
this.$emit("update:modelValue", newValue); this.$emit("update:modelValue", newValue);
}, },
}, },
}, },
methods: {
async getNewValues(selectedYMMS) {
const results = await this.updateValues();
this.values = results?.data;
if (this.values.length == 1) {
this.selectedValue = 0;
} else {
this.selectedValue =
selectedYMMS != null ? this.values.indexOf(selectedYMMS) : null;
}
},
clearValues() {
this.values = [];
this.selectedValue = null;
},
},
}; };
</script> </script>

View file

@ -15,8 +15,9 @@
ref="vehicleYearQuestion" ref="vehicleYearQuestion"
class="mb-2 mt-4" class="mb-2 mt-4"
v-model="selectedYear" v-model="selectedYear"
:isDisabled="!yearOptions.length"
:options="yearOptions"
cmsWidgetName="VehicleYearQuestion" cmsWidgetName="VehicleYearQuestion"
:updateValues="updateYearValues"
validationRules="year-required" validationRules="year-required"
placeHolderText="Select year" placeHolderText="Select year"
inputId="yearQuestionField" /> inputId="yearQuestionField" />
@ -25,8 +26,9 @@
ref="vehicleMakeQuestion" ref="vehicleMakeQuestion"
class="mb-2 mt-4" class="mb-2 mt-4"
v-model="selectedMake" v-model="selectedMake"
:isDisabled="!makeOptions.length"
:options="makeOptions"
cmsWidgetName="VehicleMakeQuestion" cmsWidgetName="VehicleMakeQuestion"
:updateValues="updateMakeValues"
validationRules="make-required" validationRules="make-required"
placeHolderText="Select make" placeHolderText="Select make"
inputId="makeQuestionField" /> inputId="makeQuestionField" />
@ -36,7 +38,8 @@
class="mb-2 mt-4" class="mb-2 mt-4"
v-model="selectedModel" v-model="selectedModel"
cmsWidgetName="VehicleModelQuestion" cmsWidgetName="VehicleModelQuestion"
:updateValues="updateModelValues" :isDisabled="!modelOptions.length"
:options="modelOptions"
validationRules="model-required" validationRules="model-required"
placeHolderText="Select model" placeHolderText="Select model"
inputId="modelQuestionField" /> inputId="modelQuestionField" />
@ -46,7 +49,8 @@
class="mb-2 mt-4" class="mb-2 mt-4"
v-model="selectedStyle" v-model="selectedStyle"
cmsWidgetName="VehicleStyleQuestion" cmsWidgetName="VehicleStyleQuestion"
:updateValues="updateStyleValues" :isDisabled="!styleOptions.length"
:options="styleOptions"
validationRules="style-required" validationRules="style-required"
placeHolderText="Select style" placeHolderText="Select style"
inputId="styleQuestionField" /> inputId="styleQuestionField" />
@ -101,10 +105,14 @@ export default {
name: "vehicle", name: "vehicle",
data() { data() {
return { return {
selectedYear: null, selectedYear: this.selectedYearfromStore(),
selectedMake: null, selectedMake: this.selectedMakefromStore(),
selectedModel: null, selectedModel: this.selectedModelfromStore(),
selectedStyle: null, selectedStyle: this.selectedStylefromStore(),
yearOptions: [],
makeOptions: [],
modelOptions: [],
styleOptions: [],
}; };
}, },
@ -113,10 +121,6 @@ export default {
validationRules: String, validationRules: String,
}, },
mounted() {
this.$refs["vehicleYearQuestion"].getNewValues(this.selectedYearfromStore);
},
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
// Call APIs // Call APIs
@ -124,6 +128,43 @@ export default {
const experimentForLogging = store.getters.applicationUser.experiments.find( const experimentForLogging = store.getters.applicationUser.experiments.find(
(e) => e.universeName === experimentUniverses.CONCEPT_FUNNEL (e) => e.universeName === experimentUniverses.CONCEPT_FUNNEL
); );
const yearQuestionInitialDataPromise = baseMixin.methods.dispatchStoreAction(
storeActions.GET_VEHICLE_YEARS,
{}
);
var makeQuestionInitialDataPromise = null;
var modelQuestionInitialDataPromise = null;
var styleQuestionInitialDataPromise = null;
if (
store.getters.order.vehicle.make &&
store.getters.order.vehicle.model &&
store.getters.order.vehicle.style
) {
makeQuestionInitialDataPromise = baseMixin.methods.dispatchStoreAction(
storeActions.GET_VEHICLE_MAKES,
{
year: store.getters.order.vehicle.year,
}
);
modelQuestionInitialDataPromise = baseMixin.methods.dispatchStoreAction(
storeActions.GET_VEHICLE_MODELS,
{
year: store.getters.order.vehicle.year,
make: store.getters.order.vehicle.make,
}
);
styleQuestionInitialDataPromise = baseMixin.methods.dispatchStoreAction(
storeActions.GET_VEHICLE_STYLES,
{
year: store.getters.order.vehicle.year,
make: store.getters.order.vehicle.make,
model: store.getters.order.vehicle.model,
}
);
}
// If the concept funnel experiment is found, as it should be when coming from safelite.com, then log the experiment exposure. // If the concept funnel experiment is found, as it should be when coming from safelite.com, then log the experiment exposure.
if (experimentForLogging !== undefined) { if (experimentForLogging !== undefined) {
@ -146,6 +187,22 @@ export default {
resultKey: "cmsContent", resultKey: "cmsContent",
promise: cmsContentPromise, promise: cmsContentPromise,
}, },
{
resultKey: "yearQuestionInitialData",
promise: yearQuestionInitialDataPromise,
},
{
resultKey: "makeQuestionInitialData",
promise: makeQuestionInitialDataPromise,
},
{
resultKey: "modelQuestionInitialData",
promise: modelQuestionInitialDataPromise,
},
{
resultKey: "styleQuestionInitialData",
promise: styleQuestionInitialDataPromise,
},
]; ];
let resultMap = await settleAllPromises(promiseResultMap); let resultMap = await settleAllPromises(promiseResultMap);
@ -153,48 +210,74 @@ export default {
// Call the "next" function to complete the transition to this page. // Call the "next" function to complete the transition to this page.
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.initializeYearComponent(resultMap.yearQuestionInitialData);
if (
makeQuestionInitialDataPromise &&
modelQuestionInitialDataPromise &&
styleQuestionInitialDataPromise
)
vm.initializeMMSComponent(
resultMap.makeQuestionInitialData,
resultMap.modelQuestionInitialData,
resultMap.styleQuestionInitialData
);
}); });
}, },
watch: { watch: {
selectedYear(year) { async selectedYear(year) {
const parsedYear = parseInt(year);
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_YEAR, parsedYear);
if (year) { if (year) {
this.$refs["vehicleMakeQuestion"].getNewValues(this.selectedMakefromStore); const result = await this.getMakeOptions(year);
this.makeOptions = result?.data;
if (this.selectedYearfromStore() !== year) {
this.selectedMake = null;
this.selectedModel = null;
this.selectedStyle = null;
}
} else { } else {
this.$refs["vehicleMakeQuestion"].clearValues(); this.makeOptions = [];
} }
}, },
selectedMake(make) { async selectedMake(make) {
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_MAKE, make, false);
if (make) { if (make) {
this.$refs["vehicleModelQuestion"].getNewValues(this.selectedModelfromStore); const result = await this.getModelOptions(this.selectedYear, make);
this.modelOptions = result?.data;
if (this.selectedMakefromStore() !== make) {
this.selectedModel = null;
this.selectedStyle = null;
}
} else { } else {
this.$refs["vehicleModelQuestion"].clearValues(); this.modelOptions = [];
} }
}, },
selectedModel(model) { async selectedModel(model) {
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_MODEL, model, false);
if (model) { if (model) {
this.$refs["vehicleStyleQuestion"].getNewValues(this.selectedStylefromStore); const result = await this.getStyleOptions(
this.selectedYear,
this.selectedMake,
model
);
this.styleOptions = result?.data;
if (this.selectedModelfromStore() !== model) {
this.selectedStyle = null;
}
} else { } else {
this.$refs["vehicleStyleQuestion"].clearValues(); this.styleOptions = [];
} }
}, },
selectedStyle(style) { selectedStyle(style) {
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_STYLE, style, false); this.setVehicle(this.selectedYear, this.selectedMake, this.selectedModel, style);
this.setVehicle();
}, },
}, },
methods: { methods: {
setVehicle() { setVehicle(year, make, model, style) {
return this.dispatchStoreAction(this.storeActions.SET_VEHICLE, { return this.dispatchStoreAction(this.storeActions.SET_VEHICLE, {
year: this.$store.getters.vehicle.year, year: year,
make: this.$store.getters.vehicle.make, make: make,
model: this.$store.getters.vehicle.model, model: model,
style: this.$store.getters.vehicle.style, style: style,
}); });
}, },
@ -207,42 +290,29 @@ export default {
}, },
navigateForward() { navigateForward() {
this.dispatchStoreAction(
storeActions.SAVE_VEHICLE,
{
year: this.selectedYear,
make: this.selectedMake,
model: this.selectedModel,
style: this.selectedStyle,
},
false
);
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route); this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
}, },
async updateYearValues() { initializeYearComponent(initialData) {
return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_YEARS, {}); this.yearOptions = initialData;
}, },
initializeMMSComponent(makeOptions, modelOptions, styleOptions) {
async updateMakeValues() { this.makeOptions = makeOptions;
return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MAKES, { this.modelOptions = modelOptions;
year: store.getters.vehicle.year, this.styleOptions = styleOptions;
});
},
async updateModelValues() {
return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MODELS, {
year: store.getters.vehicle.year,
make: store.getters.vehicle.make,
});
},
async updateStyleValues() {
return baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_STYLES, {
year: store.getters.vehicle.year,
make: store.getters.vehicle.make,
model: store.getters.vehicle.model,
});
},
},
computed: {
displayGeneric() {
return !this.selectedStyle;
}, },
selectedYearfromStore() { selectedYearfromStore() {
return store.getters.vehicle.year; return store.getters.vehicle.year?.toString();
}, },
selectedMakefromStore() { selectedMakefromStore() {
return store.getters.vehicle.make; return store.getters.vehicle.make;
@ -253,6 +323,32 @@ export default {
selectedStylefromStore() { selectedStylefromStore() {
return store.getters.vehicle.style; return store.getters.vehicle.style;
}, },
async getMakeOptions(year) {
return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MAKES, {
year: year,
});
},
async getModelOptions(year, make) {
return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_MODELS, {
year: year,
make: make,
});
},
async getStyleOptions(year, make, model) {
return await baseMixin.methods.dispatchStoreAction(storeActions.GET_VEHICLE_STYLES, {
year: year,
make: make,
model: model,
});
},
},
computed: {
displayGeneric() {
return !this.selectedStyle;
},
}, },
components: { components: {

View file

@ -1619,6 +1619,25 @@ export const actions = {
} }
}, },
saveVehicle(context, { year, make, model, style }) {
context.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
context.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
if (context.state.order.vehicle.year !== year) {
context.commit(storeMutations.UPDATE_YEAR, year);
}
if (context.state.order.vehicle.make !== make) {
context.commit(storeMutations.UPDATE_MAKE, make);
}
if (context.state.order.vehicle.model !== model) {
context.commit(storeMutations.UPDATE_MODEL, model);
}
if (context.state.order.vehicle.style !== style) {
context.commit(storeMutations.UPDATE_STYLE, style);
}
},
saveVehicleDamage( saveVehicleDamage(
context, context,
{ isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount } { isWindshieldRepair, selectedGlassToReplace, selectedWindshieldChipCount }

View file

@ -1702,6 +1702,59 @@ describe("Actions", () => {
expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null); expect(commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_IMAGE_COLOR, null);
}); });
it("saveVehicle, should save vehicle info", () => {
// Arrange
const context = state;
context.state = {
order: {
vehicle: {
year: "2016",
make: "Toyota",
model: "Accord",
style: "SUV",
},
},
};
const commit = jest.fn();
const dispatch = jest.fn();
context.commit = commit;
context.dispatch = dispatch;
//Act
const payload = {
year: "2015",
make: "Honda",
model: "Civic",
style: "Sedan",
};
actions.saveVehicle(context, payload);
//Assert
expect(dispatch).toHaveBeenNthCalledWith(
1,
storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES
);
expect(dispatch).toHaveBeenNthCalledWith(
2,
storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES
);
if (context.state.order.vehicle.year !== payload.year) {
expect(commit).toBeCalledWith(storeMutations.UPDATE_YEAR, payload.year);
}
if (context.state.order.vehicle.make !== payload.make) {
expect(commit).toBeCalledWith(storeMutations.UPDATE_MAKE, payload.make);
}
if (context.state.order.vehicle.model !== payload.model) {
expect(commit).toBeCalledWith(storeMutations.UPDATE_MODEL, payload.model);
}
if (context.state.order.vehicle.style !== payload.style) {
expect(commit).toBeCalledWith(storeMutations.UPDATE_STYLE, payload.style);
}
});
it("saveVehicleDamage, should wipe out damage if different", () => { it("saveVehicleDamage, should wipe out damage if different", () => {
// Arrange // Arrange
const context = state; const context = state;