Merge branch 'develop' into feature/CSR-941

This commit is contained in:
Matt Sykes 2022-12-13 17:29:37 -05:00
commit a8255d4134
21 changed files with 219 additions and 154 deletions

View file

@ -15,10 +15,6 @@
data-bs-target="#footerModal" data-bs-target="#footerModal"
data-bs-dismiss="modal" /> data-bs-dismiss="modal" />
</div> </div>
<!-- TODO KO DELETE FOR QUOTE MVP -->
<div class="col-auto">
<button @click="$emit('tempButtonClicked')">Heritage</button>
</div>
<div v-if="!isBackButtonHidden" class="col-auto link-col py-1 text-break"> <div v-if="!isBackButtonHidden" class="col-auto link-col py-1 text-break">
<textLink <textLink
linkType="navigation" linkType="navigation"

View file

@ -2,6 +2,7 @@
<!-- Modal --> <!-- Modal -->
<div <div
class="modal fade modal-component" class="modal fade modal-component"
v-on="{ 'hidden.bs.modal': resetButtonStyle }"
:id="this.cmsWidgetName" :id="this.cmsWidgetName"
tabindex="-1" tabindex="-1"
aria-labelledby="ModalComponentLabel" aria-labelledby="ModalComponentLabel"
@ -61,16 +62,10 @@ export default {
}, },
}, },
methods: { methods: {
setupModalEventListener() { resetButtonStyle() {
const modal = document.querySelector("#" + this.cmsWidgetName); this.$refs.buttonMain.resetButtonStyle();
modal.addEventListener("hidden.bs.modal", (event) => {
this.$refs.buttonMain.resetButtonStyle();
});
}, },
}, },
mounted() {
this.setupModalEventListener();
},
components: { components: {
buttonMain, buttonMain,
}, },

View file

@ -8,6 +8,7 @@ const applicationConfig = {
APPLICATION_NAME: "FixMyGlass", APPLICATION_NAME: "FixMyGlass",
APPLICATION_ABBREVIATION: "fmg", APPLICATION_ABBREVIATION: "fmg",
SITE_ENTRY_TRIGGER_VALUE: "FixMyGlass", SITE_ENTRY_TRIGGER_VALUE: "FixMyGlass",
CASH_ACCOUNT_NUMBER: 167132,
}; };
export { applicationConfig }; export { applicationConfig };

View file

@ -96,7 +96,7 @@ const endpoints = {
}, },
PriceOrderItems: { PriceOrderItems: {
url: "/price/api/v1/price/order-items", url: "/price/api/v1/price/order-items",
method: "POST", method: "GET",
}, },
LogExperimentExposureIfAssigned: { LogExperimentExposureIfAssigned: {
url: "/experiments/api/v1/experiments/log-exposure", url: "/experiments/api/v1/experiments/log-exposure",

View file

@ -67,6 +67,7 @@ const storeActions = {
SAVE_CAPABILITY_QUESTION_ANSWERS: "saveCapabilityQuestionAnswers", SAVE_CAPABILITY_QUESTION_ANSWERS: "saveCapabilityQuestionAnswers",
SAVE_QUOTE_PAGE_SELECTIONS: "saveQuotePageSelections", SAVE_QUOTE_PAGE_SELECTIONS: "saveQuotePageSelections",
SAVE_PAYMENT_TYPE: "savePaymentType", SAVE_PAYMENT_TYPE: "savePaymentType",
SAVE_ACCOUNT_NUMBER: "saveAccountNumber",
SAVE_SUPPORTING_ITEMS: "saveSupportingItems", SAVE_SUPPORTING_ITEMS: "saveSupportingItems",
SAVE_VAPS: "saveVaps", SAVE_VAPS: "saveVaps",
}; };

View file

@ -21,6 +21,7 @@ const storeMutations = {
UPDATE_GLASS_PARTS: "updateGlassParts", UPDATE_GLASS_PARTS: "updateGlassParts",
UPDATE_VAPS: "updateVaps", UPDATE_VAPS: "updateVaps",
UPDATE_SUPPORTING_ITEMS: "updateSupportingItems", UPDATE_SUPPORTING_ITEMS: "updateSupportingItems",
UPDATE_LINE_ITEMS_SERVER_DATA: "updateLineItemsServerData",
UPDATE_REGISTRATION_LICENSE_PLATE: "updateRegistrationLicensePlate", UPDATE_REGISTRATION_LICENSE_PLATE: "updateRegistrationLicensePlate",
UPDATE_REGISTRATION_ADDRESS: "updateRegistrationAddress", UPDATE_REGISTRATION_ADDRESS: "updateRegistrationAddress",

View file

@ -61,6 +61,33 @@ export async function navigateToHeritageFunnel({ shouldSaveSession = true, loadi
}); });
} }
export async function skipVinLookup() {
const isVinOptionalVehicle = store.getters.order.vehicle.make
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
: false;
return (
store.getters.damage.isRepair ||
isVinOptionalVehicle ||
experimentMixin.methods.hasSettingEqualTo(experimentSettings.SUPPRESS_VIN_CAPTURE, "true")
);
}
export async function skipVinLookupNotRepair() {
const isVinOptionalVehicle = store.getters.order.vehicle.make
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
: false;
return (
!store.getters.damage.isRepair &&
(isVinOptionalVehicle ||
experimentMixin.methods.hasSettingEqualTo(
experimentSettings.SUPPRESS_VIN_CAPTURE,
"true"
))
);
}
/* /*
Logic for getting the last "valid" page a user visited. Logic for getting the last "valid" page a user visited.
*/ */
@ -81,9 +108,7 @@ async function getLatestPageForRedirection() {
fmgPageValues.CAPABILITY_QUESTIONS fmgPageValues.CAPABILITY_QUESTIONS
); );
const isVinOptionalVehicle = store.getters.order.vehicle.make const skipVin = await skipVinLookup();
? await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE)
: false;
if (!vehicleMakeComponent.methods.arePagePrerequisitesValid()) { if (!vehicleMakeComponent.methods.arePagePrerequisitesValid()) {
return fmgPageValues.VEHICLE_YEAR; return fmgPageValues.VEHICLE_YEAR;
@ -107,12 +132,7 @@ async function getLatestPageForRedirection() {
} else if ( } else if (
// capture vin // capture vin
vinLookupComponent.methods.arePagePrerequisitesValid() && vinLookupComponent.methods.arePagePrerequisitesValid() &&
!store.getters.damage.isRepair && !skipVin
!isVinOptionalVehicle &&
experimentMixin.methods.hasSettingEqualTo(
experimentSettings.SUPPRESS_VIN_CAPTURE,
false
)
) { ) {
return fmgPageValues.VIN_LOOKUP; return fmgPageValues.VIN_LOOKUP;
} else { } else {

View file

@ -100,6 +100,7 @@ async function saveSessionHelper() {
accountNumber: savedSessionInfo.data.accountNumber?.toString(), accountNumber: savedSessionInfo.data.accountNumber?.toString(),
savedSessionId: savedSessionInfo.data.savedSessionId, savedSessionId: savedSessionInfo.data.savedSessionId,
crmCustomerId: savedSessionInfo.data.crmCustomerId?.toString(), crmCustomerId: savedSessionInfo.data.crmCustomerId?.toString(),
eon: savedSessionInfo.data.eon,
}, },
false false
); );

View file

@ -174,9 +174,7 @@ export default {
).parts = partFromCapabilityQuestionAnswer; ).parts = partFromCapabilityQuestionAnswer;
} }
// this.navigateForward(partsOrQuestions); this.navigateForward(partsOrQuestions);
// TODO KO delete after quote MVP
this.navigateForward(partsOrQuestions, null, this.shouldGoToHeritageQuote);
}, },
}, },
components: { components: {

View file

@ -219,40 +219,32 @@ describe("estimate.vue", () => {
}); });
}); });
describe("skipVinLookup", () => { describe("test alertInfo and isRepair", () => {
const skipOptions = [ const skipOptions = [
[true, true, true, true], [true, false, "AlertQuoteReady"],
[true, false, false, true], [false, true, "AlertQuoteVinOptional"],
[false, true, true, true], [false, false, "AlertQuoteReady"],
[false, false, false, false], [true, true, "AlertQuoteVinOptional"],
]; ];
test.each(skipOptions)( test.each(skipOptions)(
"isRepair %s, isVinOptional %s and suppressVinCapture %s should return %s", "isRepair %s, skipVinNotRepair %s alertInfo should return %s",
async (isRepair, isVinOptionalVehicle, suppressVinCapture, expectedVinSkip) => { async (isRepair, skipVinNotRepair, expectedAlertInfo) => {
const { wrapper } = setupMocks({}); const { wrapper } = setupMocks({});
await wrapper.setData({ await wrapper.setData({
isVinOptionalVehicle: isVinOptionalVehicle, skipVinNotRepair: skipVinNotRepair,
}); });
store.commit(storeMutations.UPDATE_IS_REPAIR, isRepair); store.commit(storeMutations.UPDATE_IS_REPAIR, isRepair);
const mockExperimentsList = [
{
universeName: "ConceptFunnel",
settings: {
SuppressVinCapture: suppressVinCapture,
},
},
];
store.commit(storeMutations.UPDATE_EXPERIMENTS, mockExperimentsList);
expect(wrapper.vm.skipVinLookup).toEqual(expectedVinSkip); expect(wrapper.vm.alertInfo).toEqual(expectedAlertInfo);
expect(wrapper.vm.isRepair).toEqual(isRepair);
} }
); );
}); });
function setupMocks({ function setupMocks({
groupName = "estimate", groupName = "estimate",
isVinOptionalVehicle = false, skipVin = false,
cmsQuestionText = "Let's get your VIN. Or we can look it up for you!", cmsQuestionText = "Let's get your VIN. Or we can look it up for you!",
cmsAnswers = [ cmsAnswers = [
{ Name: "Provide my VIN manually Most specific to your vehicle" }, { Name: "Provide my VIN manually Most specific to your vehicle" },
@ -284,7 +276,10 @@ function setupMocks({
mountOptions["attachTo"] = document.body; mountOptions["attachTo"] = document.body;
const wrapper = shallowMount(estimate, mountOptions); const wrapper = shallowMount(estimate, mountOptions);
wrapper.vm.isVinOptionalVehicle = isVinOptionalVehicle; wrapper.vm.skipVin = skipVin;
wrapper.vm.getZipCodeData = jest
.fn()
.mockReturnValue({ isValid: true, isServiceable: true, state: "OH" });
return { wrapper, apiPromise }; return { wrapper, apiPromise };
} }

View file

@ -6,7 +6,7 @@
<vehicleBanner cmsWidgetName="VehicleBannerWidget" /> <vehicleBanner cmsWidgetName="VehicleBannerWidget" />
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" /> <funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" />
<div class="fade-on-route-transition sub-container make-tall"> <div class="fade-on-route-transition sub-container make-tall">
<div v-if="!skipVinLookup"> <div v-if="!skipVin">
<alert <alert
class="vinLookupMethodHeading" class="vinLookupMethodHeading"
cmsWidgetName="AlertVinLookupQuestion" cmsWidgetName="AlertVinLookupQuestion"
@ -103,10 +103,14 @@ import { Form, defineRule } from "vee-validate";
import store from "@/store"; import store from "@/store";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import { vinLookupMethodSelections } from "@/constants/vin-lookup-method-selections.js"; import { vinLookupMethodSelections } from "@/constants/vin-lookup-method-selections.js";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; import {
skipVinLookup,
skipVinLookupNotRepair,
} from "@/helpers/heritage-integration/navigation-helper";
import experimentMixin from "@/mixins/experiment-mixin"; import experimentMixin from "@/mixins/experiment-mixin";
import { experimentSettings } from "@/constants/experiments"; import { experimentSettings } from "@/constants/experiments";
import vinPagesMixin from "@/mixins/vin-pages-mixin"; import vinPagesMixin from "@/mixins/vin-pages-mixin";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
// Define Validation Rules // Define Validation Rules
defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED)); defineRule("zip-required", required(errorMessages.SERVICE_ZIP_REQUIRED));
@ -131,7 +135,8 @@ export default {
emailAddress: this.getEmailFromStore(), emailAddress: this.getEmailFromStore(),
displayInvalidZipAlert: false, displayInvalidZipAlert: false,
displayNonServiceableZipAlert: false, displayNonServiceableZipAlert: false,
isVinOptionalVehicle: false, skipVin: false,
skipVinNotRepair: false,
}; };
}, },
@ -148,14 +153,16 @@ export default {
]; ];
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
const isVinOptionalVehicle = await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE); const skipVin = await skipVinLookup();
const skipVinNotRepair = await skipVinLookupNotRepair();
next((vm) => { next((vm) => {
vm.isVinOptionalVehicle = isVinOptionalVehicle; vm.skipVin = skipVin;
vm.skipVinNotRepair = skipVinNotRepair;
if (resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.includes("|")) { if (resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.includes("|")) {
const forwardTextOption = const forwardTextOption =
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.split("|"); resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText.split("|");
if (store.getters.damage.isRepair || vm.isVinOptionalVehicle) { if (skipVin) {
resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText = resultMap.cmsContent.FunnelFooterWidget.ForwardButtonText =
forwardTextOption[1]; forwardTextOption[1];
} else { } else {
@ -182,9 +189,8 @@ export default {
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route); this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
}, },
async forwardButtonAction() { async forwardButtonAction() {
if (this.skipVinLookup) { if (this.skipVin) {
const zipCodeData = await this.getZipCodeData(this.serviceZipCode); const zipCodeData = await this.getZipCodeData(this.serviceZipCode);
await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false); await this.dispatchStoreAction(storeActions.SAVE_EMAIL, this.emailAddress, false);
await this.dispatchStoreAction( await this.dispatchStoreAction(
storeActions.SAVE_SERVICE_LOCATION, storeActions.SAVE_SERVICE_LOCATION,
@ -264,25 +270,8 @@ export default {
isRepair() { isRepair() {
return store.getters.damage.isRepair; return store.getters.damage.isRepair;
}, },
skipVinLookup() {
return (
this.isRepair ||
this.isVinOptionalVehicle ||
experimentMixin.methods.hasSettingEqualTo(
experimentSettings.SUPPRESS_VIN_CAPTURE,
true
)
);
},
alertInfo() { alertInfo() {
return (this.isVinOptionalVehicle || return this.skipVinNotRepair ? "AlertQuoteVinOptional" : "AlertQuoteReady";
experimentMixin.methods.hasSettingEqualTo(
experimentSettings.SUPPRESS_VIN_CAPTURE,
true
)) &&
!this.isRepair
? "AlertQuoteVinOptional"
: "AlertQuoteReady";
}, },
}, },
watch: { watch: {

View file

@ -158,9 +158,7 @@ export default {
]; ];
} }
// this.navigateForward(partsOrQuestions); this.navigateForward(partsOrQuestions);
// TODO KO delete after quote MVP
this.navigateForward(partsOrQuestions, null, this.shouldGoToHeritageQuote);
}, },
}, },
components: { components: {

View file

@ -25,17 +25,19 @@
groupName="ServicePackageQuestion" groupName="ServicePackageQuestion"
:availableLineItems="availableLineItems" :availableLineItems="availableLineItems"
:isInsuranceSelected="isInsuranceSelected" :isInsuranceSelected="isInsuranceSelected"
@vapsItemsSelected="vapsItemsSelectedAction" /> @vapsItemsSelected="vapsItemsSelectedAction"
validationRules="option-required"
isRequired />
<textBlock <textBlock
cmsWidgetName="quoteDisclaimer" cmsWidgetName="quoteDisclaimer"
justifyText="left" justifyText="left"
typeStyle="caption" typeStyle="caption"
class="mt-4" /> class="mt-4" />
<modal cmsWidgetName="EstimateRainDefenseModal" /> <modal cmsWidgetName="RainDefenseModal" />
<modal cmsWidgetName="EstimateFrontWiperModal" /> <modal cmsWidgetName="FrontWiperModal" />
<modal cmsWidgetName="EstimateRearWiperModal" /> <modal cmsWidgetName="RearWiperModal" />
<modal cmsWidgetName="EstimateRecalModal" /> <modal cmsWidgetName="RecalModal" />
<funnel-footer <funnel-footer
cmsWidgetName="FunnelFooterWidget" cmsWidgetName="FunnelFooterWidget"
:isForwardActionDisabled="!meta.valid" :isForwardActionDisabled="!meta.valid"
@ -64,14 +66,19 @@ import { settleAllPromises } from "@/helpers/layout-helper";
import { storeActions } from "@/constants/store-actions"; import { storeActions } from "@/constants/store-actions";
import store from "@/store"; import store from "@/store";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { Form } from "vee-validate"; import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages";
import { Form, defineRule } from "vee-validate";
import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper"; import { navigateToHeritageFunnel } from "@/helpers/heritage-integration/navigation-helper";
import { applicationConfig } from "@/constants/application-config";
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
export default { export default {
name: "quote", name: "quote",
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
// Call APIs // Call APIs
const cmsContent = await fetchCmsContentForPage(to.query.fmgPage); const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
const wipersPromise = baseMixin.methods.dispatchStoreAction(storeActions.GET_WIPERS); const wipersPromise = baseMixin.methods.dispatchStoreAction(storeActions.GET_WIPERS);
const rainDefensePromise = baseMixin.methods.dispatchStoreAction( const rainDefensePromise = baseMixin.methods.dispatchStoreAction(
storeActions.GET_RAIN_DEFENSE storeActions.GET_RAIN_DEFENSE
@ -81,6 +88,10 @@ export default {
); );
const promiseResultMap = [ const promiseResultMap = [
{
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{ {
resultKey: "wipers", resultKey: "wipers",
promise: wipersPromise, promise: wipersPromise,
@ -112,11 +123,10 @@ 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(cmsContent); vm.setCmsContent(resultMap.cmsContent);
vm.supportingItems = resultMap.supportingItems; vm.supportingItems = resultMap.supportingItems;
vm.availableLineItems = pricingResults; vm.availableLineItems = pricingResults;
vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(); vm.isInsuranceSelected = vm.getDefaultIsInsuranceSelectedValue(vm.availableLineItems);
}); });
}, },
data() { data() {
@ -137,19 +147,28 @@ export default {
store.getters.order.lineItems.glassParts.length > 0)) store.getters.order.lineItems.glassParts.length > 0))
); );
}, },
getDefaultIsInsuranceSelectedValue() { getDefaultIsInsuranceSelectedValue(availableLineItems) {
const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance; const defaultIsInsuranceSelectedValue = this.$store.getters.order.payment.isInsurance;
if (defaultIsInsuranceSelectedValue != null) { if (defaultIsInsuranceSelectedValue != null) {
return defaultIsInsuranceSelectedValue; return defaultIsInsuranceSelectedValue;
} else { } else {
return this.availableLineItems return availableLineItems
? baseMixin.methods.getTierOnePackagePrice(this.availableLineItems) > 500 ? baseMixin.methods.getTierOnePackagePrice(availableLineItems) > 500
: null; : null;
} }
}, },
vapsItemsSelectedAction(vapsItemsSelected) { vapsItemsSelectedAction(vapsItemsSelected) {
this.selectedVaps = vapsItemsSelected; this.selectedVaps = vapsItemsSelected;
}, },
filterOutFees(currentSupportingItems) {
const filteredSupportingItems = currentSupportingItems.filter((item) => {
return (
!item.partType.includes("FEE") ||
(item.partType === "REPAIR FEE" && item.partNumber != "SUPPLIES-REPAIR")
);
});
return filteredSupportingItems;
},
backButtonAction() { backButtonAction() {
vehicleQuestionsMixin.methods.navigateBack(this); vehicleQuestionsMixin.methods.navigateBack(this);
}, },
@ -159,6 +178,16 @@ export default {
this.isInsuranceSelected, this.isInsuranceSelected,
false false
); );
if (!this.isInsuranceSelected) {
this.dispatchStoreAction(
this.storeActions.SAVE_ACCOUNT_NUMBER,
applicationConfig.CASH_ACCOUNT_NUMBER,
false
);
}
if (this.$store.getters.order.accountNumber != applicationConfig.CASH_ACCOUNT_NUMBER) {
this.supportingItems = this.filterOutFees(this.supportingItems);
}
this.dispatchStoreAction( this.dispatchStoreAction(
this.storeActions.SAVE_SUPPORTING_ITEMS, this.storeActions.SAVE_SUPPORTING_ITEMS,
this.supportingItems, this.supportingItems,

View file

@ -5,7 +5,8 @@
buttonTypeString="servicePackageRadio" buttonTypeString="servicePackageRadio"
:buttonTypeObject="servicePackageRadio" :buttonTypeObject="servicePackageRadio"
v-model="selectedPackageName" v-model="selectedPackageName"
isRequired /> :validationRules="validationRules"
:isRequired="isRequired" />
</template> </template>
<script> <script>
@ -28,6 +29,8 @@ export default {
groupName: String, groupName: String,
cashCmsWidgetName: String, cashCmsWidgetName: String,
insuranceCmsWidgetName: String, insuranceCmsWidgetName: String,
validationRules: String,
isRequired: Boolean,
isInsuranceSelected: Boolean, isInsuranceSelected: Boolean,
availableLineItems: null, availableLineItems: null,
}, },
@ -185,7 +188,7 @@ export default {
item.partType.toUpperCase() === partTypeStrings.FRONT_WIPER) || item.partType.toUpperCase() === partTypeStrings.FRONT_WIPER) ||
(priceRearWipers && item.partType.toUpperCase() === partTypeStrings.REAR_WIPER) (priceRearWipers && item.partType.toUpperCase() === partTypeStrings.REAR_WIPER)
) { ) {
vapsPrice += item.price; vapsPrice += baseMixin.methods.getTotalLineItemPrice(item);
} }
}); });
return vapsPrice; return vapsPrice;
@ -204,7 +207,7 @@ export default {
(priceRainDefense && (priceRainDefense &&
item.partType.toUpperCase() === partTypeStrings.RAIN_DEFENSE) item.partType.toUpperCase() === partTypeStrings.RAIN_DEFENSE)
) { ) {
vapsPrice += item.price; vapsPrice += baseMixin.methods.getTotalLineItemPrice(item);
} }
}); });
return vapsPrice; return vapsPrice;

View file

@ -35,7 +35,6 @@
cmsWidgetName="FunnelFooterWidget" cmsWidgetName="FunnelFooterWidget"
ref="funnelFooter" ref="funnelFooter"
:isForwardActionDisabled="isForwardActionDisabled" :isForwardActionDisabled="isForwardActionDisabled"
@tempButtonClicked="() => handleTempButtonClicked(this)"
@back-click="navigateBack" @back-click="navigateBack"
@ForwardClicked="forwardButtonAction" /> @ForwardClicked="forwardButtonAction" />
</div> </div>
@ -189,10 +188,8 @@ export default {
false false
); );
// TODO KO delete after quote MVP
this.navigateForward(matchedParts, null, this.shouldGoToHeritageQuote);
// Navigate to the next page // Navigate to the next page
// this.navigateForward(matchedParts); this.navigateForward(matchedParts);
}, },
LoadInitialPartsData() { LoadInitialPartsData() {

View file

@ -100,7 +100,6 @@
cmsWidgetName="FunnelFooterWidget" cmsWidgetName="FunnelFooterWidget"
ref="funnelFooter" ref="funnelFooter"
:isForwardActionDisabled="!meta.valid" :isForwardActionDisabled="!meta.valid"
@tempButtonClicked="() => handleTempButtonClicked(this)"
@back-clicked="backButtonAction" @back-clicked="backButtonAction"
@ForwardClicked="forwardButtonAction" /> @ForwardClicked="forwardButtonAction" />
</div> </div>

View file

@ -72,11 +72,14 @@ export default {
partType != partTypeStrings.REAR_WIPER && partType != partTypeStrings.REAR_WIPER &&
partType != partTypeStrings.RAIN_DEFENSE partType != partTypeStrings.RAIN_DEFENSE
) { ) {
totalPrice += lineItem.price; totalPrice += this.getTotalLineItemPrice(lineItem);
} }
}); });
return totalPrice; return totalPrice;
}, },
getTotalLineItemPrice(lineItem) {
return lineItem.kitPrice + lineItem.laborAmount + lineItem.sellingPrice;
},
}, },
computed: { computed: {
storeActions() { storeActions() {

View file

@ -7,12 +7,6 @@ import baseMixin from "@/mixins/base-mixin.js";
import store from "@/store"; import store from "@/store";
export default { export default {
data() {
// TODO KO DELETE AFTER QUOTE MVP
return {
shouldGoToHeritageQuote: false,
};
},
methods: { methods: {
hasPartQuestions(partsOrQuestions) { hasPartQuestions(partsOrQuestions) {
return partsOrQuestions?.some((pq) => pq.partQuestions?.length > 0); return partsOrQuestions?.some((pq) => pq.partQuestions?.length > 0);
@ -48,7 +42,9 @@ export default {
requiresCapabilityQuestions: singlePart.requiresCapabilityQuestions, requiresCapabilityQuestions: singlePart.requiresCapabilityQuestions,
recalibrationType: singlePart.recalibrationType, recalibrationType: singlePart.recalibrationType,
childParts: singlePart.childParts, childParts: singlePart.childParts,
price: singlePart.price, kitPrice: singlePart.kitPrice,
sellingPrice: singlePart.sellingPrice,
laborAmount: singlePart.laborAmount,
}); });
} }
}); });
@ -353,9 +349,8 @@ export default {
} }
} }
}, },
// TODO KO Delete `shouldGoToHeritageQuote`
// Can't use `this` because navigateForward is also called from vin-pages-mixin // Can't use `this` because navigateForward is also called from vin-pages-mixin
async navigateForward(partsOrQuestions, vm, shouldGoToHeritageQuote) { async navigateForward(partsOrQuestions, vm) {
const self = vm ?? this; const self = vm ?? this;
const currentPage = self.$route.query.fmgPage; const currentPage = self.$route.query.fmgPage;
@ -450,36 +445,61 @@ export default {
self.$store.commit(storeMutations.UPDATE_GLASS_PARTS, collectedGlassParts); self.$store.commit(storeMutations.UPDATE_GLASS_PARTS, collectedGlassParts);
const payment = store.getters.payment; const payment = store.getters.payment;
shouldGoToHeritageQuote ||
(payment.isInsurance && payment.insuranceCoverage.isVerified) if (payment.isInsurance && payment.insuranceCoverage.isVerified) {
? navigateToHeritageFunnel({ loadingModal: self.$refs.loadingModal }) navigateToHeritageFunnel({ loadingModal: self.$refs.loadingModal });
: self.$router.navigateWithSaving( } else {
self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS, self.$router.navigateWithSaving(
self.$route self.navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
); self.$route
);
}
} }
}, },
// Can't use `this` because navigateForward is also called from quote // Can't use `this` because navigateForward is also called from quote
async navigateBack(vm) { async navigateBack(vm) {
const self = vm ?? this; const self = vm ?? this;
const partsOrQuestions = ( const currentPage = self.$route.query.fmgPage;
self.$store.getters.pageData(fmgPageValues.CAPABILITY_QUESTIONS) ?? const pageDataCapabilityQuestions = self.$store.getters.pageData(
self.$store.getters.pageData(fmgPageValues.MOLDING_QUESTIONS) ?? fmgPageValues.CAPABILITY_QUESTIONS
self.$store.getters.pageData(fmgPageValues.VEHICLE_PARTS) ?? );
self.$store.getters.pageData(fmgPageValues.PART_QUESTIONS) const pageDataMoldingQuestions = self.$store.getters.pageData(
)?.partsOrQuestions; fmgPageValues.MOLDING_QUESTIONS
const hasPartQuestions = this.hasPartQuestions(partsOrQuestions); );
const pageDataVehicleParts = self.$store.getters.pageData(fmgPageValues.VEHICLE_PARTS);
const pageDataPartQuestions = self.$store.getters.pageData(
fmgPageValues.PART_QUESTIONS
);
let currentPartsOrQuestions = null;
if (
currentPage !== fmgPageValues.CAPABILITY_QUESTIONS &&
!!pageDataCapabilityQuestions
) {
currentPartsOrQuestions = pageDataCapabilityQuestions?.partsOrQuestions;
} else if (
currentPage !== fmgPageValues.MOLDING_QUESTIONS &&
!!pageDataMoldingQuestions
) {
currentPartsOrQuestions = pageDataMoldingQuestions?.partsOrQuestions;
} else if (currentPage !== fmgPageValues.VEHICLE_PARTS && !!pageDataVehicleParts) {
currentPartsOrQuestions = pageDataVehicleParts?.partsOrQuestions;
} else if (currentPage !== fmgPageValues.PARTS_QUESTIONS && !!pageDataPartQuestions) {
currentPartsOrQuestions = pageDataPartQuestions?.partsOrQuestions;
}
const hasPartQuestions = this.hasPartQuestions(currentPartsOrQuestions);
const hasGlassLocationWithMultipleParts = const hasGlassLocationWithMultipleParts =
this.hasGlassLocationWithMultipleParts(partsOrQuestions); this.hasGlassLocationWithMultipleParts(currentPartsOrQuestions);
const hasChildPartQuestions = this.hasChildPartQuestions(partsOrQuestions); const hasChildPartQuestions = this.hasChildPartQuestions(currentPartsOrQuestions);
const hasCapabilityQuestions = this.hasCapabilityQuestions(partsOrQuestions); const hasCapabilityQuestions = this.hasCapabilityQuestions(currentPartsOrQuestions);
const skipVinLookup = await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE); const skipVinLookup = await store.dispatch(storeActions.IS_VIN_OPTIONAL_VEHICLE);
let backNavigationScenario = self.$store.getters.vehicle.vin let backNavigationScenario = self.$store.getters.vehicle.vin
? navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS ? navigationScenarios.CLICKED_BACK_WITH_VIN_AND_NO_MORE_QUESTIONS
: navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS; : navigationScenarios.CLICKED_BACK_WITH_NO_VIN_NOR_QUESTIONS;
const currentPage = self.$route.query.fmgPage;
if ( if (
hasCapabilityQuestions && hasCapabilityQuestions &&
this.currentPageComesAfterPage(currentPage, fmgPageValues.CAPABILITY_QUESTIONS) this.currentPageComesAfterPage(currentPage, fmgPageValues.CAPABILITY_QUESTIONS)
@ -507,9 +527,5 @@ export default {
self.$router.navigateWithoutSaving(backNavigationScenario, self.$route); self.$router.navigateWithoutSaving(backNavigationScenario, self.$route);
}, },
// TODO KO delete this after quote mvp
async handleTempButtonClicked(vm) {
this.shouldGoToHeritageQuote = true;
},
}, },
}; };

View file

@ -4,12 +4,6 @@ import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
import { saveSession } from "@/helpers/heritage-integration/order-helper.js"; import { saveSession } from "@/helpers/heritage-integration/order-helper.js";
export default { export default {
data() {
// TODO KO DELETE AFTER QUOTE MVP
return {
shouldGoToHeritageQuote: false,
};
},
methods: { methods: {
async navigateForwardWithSingleCarMatch() { async navigateForwardWithSingleCarMatch() {
// If we have not already saved a session, we need to save one now before the lengthy call to getPartsOrQuestions // If we have not already saved a session, we need to save one now before the lengthy call to getPartsOrQuestions
@ -20,17 +14,7 @@ export default {
const result = await this.dispatchStoreAction(storeActions.GET_PARTS_OR_QUESTIONS); const result = await this.dispatchStoreAction(storeActions.GET_PARTS_OR_QUESTIONS);
const partsOrQuestions = result.data.partsOrQuestions; const partsOrQuestions = result.data.partsOrQuestions;
// TODO KO delete `this.shouldGoToHeritageQuote` vehicleQuestionsMixin.methods.navigateForward(partsOrQuestions, this);
vehicleQuestionsMixin.methods.navigateForward(
partsOrQuestions,
this,
this.shouldGoToHeritageQuote
);
},
// TODO KO delete this after quote mvp
async handleTempButtonClicked(vm) {
this.shouldGoToHeritageQuote = true;
await vm.forwardButtonAction();
}, },
}, },
}; };

View file

@ -149,6 +149,9 @@ export const mutations = {
updateSupportingItems(state, partsData) { updateSupportingItems(state, partsData) {
state.order.lineItems.supportingItems = partsData; state.order.lineItems.supportingItems = partsData;
}, },
updateLineItemsServerData(state, serverData) {
state.order.lineItems.serverData = serverData;
},
updatePageData(state, pageData) { updatePageData(state, pageData) {
state.applicationUser.pageData[pageData.page] = pageData.data; state.applicationUser.pageData[pageData.page] = pageData.data;
}, },
@ -904,14 +907,14 @@ export const actions = {
const carId = context.getters.vehicle.carId; const carId = context.getters.vehicle.carId;
const isRepair = context.getters.damage.isRepair; const isRepair = context.getters.damage.isRepair;
const numberOfChips = context.getters.damage.numberOfChips; const numberOfChips = context.getters.damage.numberOfChips;
const parentAccountNumber = context.getters.order.accountNumber.toString();
return globalMethods.callHttpClient({ return globalMethods.callHttpClient({
method: endpoints.GetSupportingItems.method, method: endpoints.GetSupportingItems.method,
endpoint: endpoints.GetSupportingItems.url, endpoint: endpoints.GetSupportingItems.url,
payload: { payload: {
carId: carId, carId: carId,
serviceType: isRepair ? "Repair" : "Replace", serviceType: isRepair ? "Repair" : "Replace",
parentAccountNumber: parentAccountNumber, parentAccountNumber: applicationConfig.CASH_ACCOUNT_NUMBER,
parts: glassPartsArray, parts: glassPartsArray,
numberOfRepairChips: isRepair ? numberOfChips : 0, numberOfRepairChips: isRepair ? numberOfChips : 0,
}, },
@ -1008,7 +1011,7 @@ export const actions = {
}, },
isInsurance: order.payment.isInsurance ?? false, isInsurance: order.payment.isInsurance ?? false,
}, },
accountNumber: order.accountNumber?.toString(), accountNumber: order.accountNumber,
providerNumber: "", providerNumber: "",
serviceLocation: { serviceLocation: {
streetAddress: order.serviceLocation.address, streetAddress: order.serviceLocation.address,
@ -1022,6 +1025,7 @@ export const actions = {
referralDate: order.referralDate, referralDate: order.referralDate,
referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place referralNumber: order.referralNumber?.toString(), // TODO It'd be nice to save these as strings in the first place
referralSequenceNumber: order.referralNumber?.toString(), // TODO Pass the referralSequence number once insurance flow creates it referralSequenceNumber: order.referralNumber?.toString(), // TODO Pass the referralSequence number once insurance flow creates it
eon: order.eon,
}, },
}, },
}); });
@ -1379,6 +1383,9 @@ export const actions = {
savePaymentType(context, isInsurance) { savePaymentType(context, isInsurance) {
context.commit(storeMutations.UPDATE_IS_INSURANCE, isInsurance); context.commit(storeMutations.UPDATE_IS_INSURANCE, isInsurance);
}, },
saveAccountNumber(context, accountNumber) {
context.commit(storeMutations.UPDATE_PARENT_ACCT_NUMBER, accountNumber);
},
saveSupportingItems(context, supportingItems) { saveSupportingItems(context, supportingItems) {
context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems); context.commit(storeMutations.UPDATE_SUPPORTING_ITEMS, supportingItems);
}, },
@ -1386,11 +1393,34 @@ export const actions = {
context.commit(storeMutations.UPDATE_VAPS, vaps); context.commit(storeMutations.UPDATE_VAPS, vaps);
}, },
// Price order actions // Price order actions
// PLACEHOLDER, WILL CHANGE WHEN PRICING END POINT IS IMPLEMENTED async priceOrderItems(context, availableLineItems) {
priceOrderItems(context, availableLineItems) { const availableLineItemsFormattedForRequest = availableLineItems
availableLineItems.forEach((lineItem) => { .map((lineItem) => `&LineItems=${lineItem.partNumber}`)
lineItem["price"] = parseFloat((Math.random() * 100).toFixed(2)); .join("");
const vehicle = context.getters.order.vehicle;
let queryString =
`ParentAccountNumber=${applicationConfig.CASH_ACCOUNT_NUMBER}` +
`&CTU=${context.getters.order.serviceLocation.zipCodeCtu}` +
`&CarId=${vehicle.carId}` +
`&Make=${vehicle.make}` +
`&Model=${vehicle.model}` +
`&Year=${vehicle.year}` +
`&EON=${context.getters.order.eon}` +
`&ZipCode=${context.getters.order.serviceLocation.zipCode}` +
`${availableLineItemsFormattedForRequest}`;
const lineItemServerData = context.getters.order.lineItems.serverData;
if (lineItemServerData) {
queryString += `&ServerData=${lineItemServerData}`;
}
const response = await globalMethods.callHttpClient({
method: endpoints.PriceOrderItems.method,
endpoint: `${endpoints.PriceOrderItems.url}?${queryString}`,
}); });
context.commit(storeMutations.UPDATE_LINE_ITEMS_SERVER_DATA, response.data.serverData);
availableLineItems = addPricesToLineItems(availableLineItems, response.data.lineItems);
return availableLineItems; return availableLineItems;
}, },
// Misc order actions // Misc order actions
@ -1540,3 +1570,15 @@ function convertGlassPieceNamingFromApi(glassArray) {
}); });
return glassArray; return glassArray;
} }
function addPricesToLineItems(lineItems, pricingLineItems) {
lineItems.forEach((lineItem) => {
let pricedLineItem = pricingLineItems.find(
(pricingLineItem) => pricingLineItem.partNumber === lineItem.partNumber
);
lineItem.laborAmount = pricedLineItem.laborAmount;
lineItem.sellingPrice = pricedLineItem.sellingPrice;
lineItem.kitPrice = pricedLineItem.kitPrice;
});
return lineItems;
}

View file

@ -55,9 +55,6 @@ export default {
this.isLoaderDisplayed = false; this.isLoaderDisplayed = false;
}, },
}, },
mounted() {
this.isLoaderDisplayed = false;
},
components: { components: {
loader, loader,
}, },