418 lines
16 KiB
Vue
418 lines
16 KiB
Vue
<template>
|
|
<buttonQuestion
|
|
ref="buttonQuestion"
|
|
:answers="servicePackageAnswers"
|
|
:groupName="groupName"
|
|
buttonTypeString="servicePackageRadio"
|
|
:buttonTypeObject="hasPricingByDay() ? servicePackageRadioExperiment : servicePackageRadio"
|
|
v-model="selectedPackageName"
|
|
:validationRules="validationRules"
|
|
:isRequired="isRequired"
|
|
:logDisplayedValuesEvent="true"
|
|
:isInsuranceSelected="isInsuranceSelected" />
|
|
</template>
|
|
|
|
<script>
|
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
|
import baseMixin from "@/mixins/base-mixin.js";
|
|
import { processIfStatements } from "@/helpers/cms-content-helper";
|
|
import servicePackageRadio from "./service-package-radio/service-package-radio";
|
|
import servicePackageRadioExperiment from "@/experiment-components/service-package-radio";
|
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
|
import { packageNames } from "@/constants/package-names";
|
|
import {
|
|
shouldFrontWipersBeAvailable,
|
|
shouldRearWipersBeAvailable,
|
|
shouldRainDefenseBeAvailable,
|
|
getAvailablePackages,
|
|
getHighestRequiredTier,
|
|
getPackageContents,
|
|
containsLineItemWithPartType,
|
|
findLineItemsWithPartType,
|
|
getPackageNameByType,
|
|
getDiscountedPackageName,
|
|
} from "@/helpers/service-package-helper";
|
|
import {
|
|
getPromosThatMatchLineItemsOnOrder,
|
|
removeVapsPromosFromPromoArray,
|
|
getPromosWithAddableVaps,
|
|
getLineItemsThatMatchPromos,
|
|
} from "@/helpers/promotions-helper";
|
|
import { containsRecalParts, getItemsWithoutRecalParts } from "@/helpers/recal-helper";
|
|
import experimentMixin from "@/mixins/experiment-mixin.js";
|
|
import { experimentSettings } from "@/constants/experiments";
|
|
|
|
export default {
|
|
name: "servicePackageQuestion",
|
|
props: {
|
|
groupName: String,
|
|
cashCmsWidgetName: String,
|
|
insuranceCmsWidgetName: String,
|
|
validationRules: String,
|
|
isRequired: Boolean,
|
|
isInsuranceSelected: Boolean,
|
|
availableLineItems: null,
|
|
activePromos: null,
|
|
servicePackage: null,
|
|
isRecalibrationOnOrder: Boolean,
|
|
shouldHideRecalibration: Boolean,
|
|
},
|
|
data() {
|
|
return {
|
|
servicePackageRadio: servicePackageRadio,
|
|
servicePackageRadioExperiment: servicePackageRadioExperiment,
|
|
selectedPackageName: null,
|
|
};
|
|
},
|
|
watch: {
|
|
availableLineItems() {
|
|
if (
|
|
this.$store.getters.payment.isInsurance != null ||
|
|
getPromosWithAddableVaps(this.activePromos).length ||
|
|
this.servicePackage != null
|
|
) {
|
|
this.selectDefaultPackage();
|
|
}
|
|
},
|
|
activePromos() {
|
|
if (this.activePromos?.length) this.selectDefaultPackage();
|
|
},
|
|
selectedPackageName(newValue) {
|
|
const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue);
|
|
this.$emit("vapsItemsSelected", VapsProductsInSelectedPackage);
|
|
const servicePackageDiscountPartInSelectedPackage =
|
|
this.getServicePackageDiscountPartForSelectedPackage(newValue);
|
|
let supportingItems = this.supportingLineItems;
|
|
if (
|
|
containsLineItemWithPartType(
|
|
partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
|
|
supportingItems
|
|
)
|
|
) {
|
|
supportingItems = supportingItems.filter(
|
|
(item) => item.partType !== partTypeStrings.SERVICE_PACKAGE_DISCOUNT
|
|
);
|
|
}
|
|
if (
|
|
servicePackageDiscountPartInSelectedPackage?.length > 0 &&
|
|
supportingItems != null
|
|
) {
|
|
supportingItems.push(servicePackageDiscountPartInSelectedPackage[0]);
|
|
}
|
|
|
|
this.$emit("servicePackageDiscountSelected", supportingItems);
|
|
},
|
|
servicePackage(newValue) {
|
|
if (newValue !== null) {
|
|
this.selectDefaultPackage();
|
|
}
|
|
},
|
|
},
|
|
computed: {
|
|
nullSafeAvailableLineItems() {
|
|
return this.availableLineItems ?? [];
|
|
},
|
|
supportingLineItems() {
|
|
return this.$store.getters.lineItems?.supportingItems;
|
|
},
|
|
servicePackageAnswers() {
|
|
const cmsWidgetName = this.isInsuranceSelected
|
|
? this.insuranceCmsWidgetName
|
|
: this.cashCmsWidgetName;
|
|
let cmsAnswersContent = this.getCmsContent(cmsWidgetName, "Answers");
|
|
if (!cmsAnswersContent) {
|
|
return null;
|
|
}
|
|
|
|
const availablePackages = getAvailablePackages(
|
|
this.glassToReplace,
|
|
this.nullSafeAvailableLineItems,
|
|
this.isRepair
|
|
);
|
|
|
|
cmsAnswersContent = cmsAnswersContent.filter((answer) =>
|
|
availablePackages.some((tier) => answer.Name === tier.packageName)
|
|
);
|
|
|
|
const modifiedAnswers = cmsAnswersContent.map((answer) => ({
|
|
value: answer.Name,
|
|
buttonLabel: this.getHeaderTextFromCms(answer.SubWidgetName),
|
|
buttonLabelSubCopy: this.getSubheaderTextFromCms(answer.SubWidgetName),
|
|
buttonBodyCopy: this.getBodyTextFromCms(answer.SubWidgetName),
|
|
//The package supports service-package-discount if it has the text value in CMS
|
|
buttonAuxillaryCopy: this.isInsuranceSelected
|
|
? this.getDiscountedPackagePriceString(answer.Name, false)
|
|
: this.getDiscountedPackagePriceString(
|
|
answer.Name,
|
|
this.isServicePackageDiscountOnOrder &&
|
|
this.discountPackageNames == answer.Name
|
|
),
|
|
buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName),
|
|
additionalButtonData: {
|
|
strikeThroughPrice: this.getPackagePriceString(answer.Name),
|
|
servicePackageDiscount:
|
|
this.isServicePackageDiscountOnOrder &&
|
|
this.discountPackageNames == answer.Name,
|
|
Text: this.isInsuranceSelected
|
|
? false
|
|
: "Special: Save $" + this.getServicePackageDiscountPrice(),
|
|
},
|
|
}));
|
|
this.$emit("currentNumberOfPackages", modifiedAnswers.length);
|
|
return modifiedAnswers;
|
|
},
|
|
isServicePackageDiscountOnOrder() {
|
|
return containsLineItemWithPartType(
|
|
partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
|
|
this.nullSafeAvailableLineItems
|
|
);
|
|
},
|
|
discountPackageNames() {
|
|
const discountServicePackage = experimentMixin.methods.getSettingValue(
|
|
experimentSettings.PROMO_ON_PACKAGE
|
|
);
|
|
return getDiscountedPackageName(discountServicePackage);
|
|
},
|
|
frontWipersApplicableForTierTwo() {
|
|
return shouldFrontWipersBeAvailable(
|
|
this.glassToReplace,
|
|
this.nullSafeAvailableLineItems,
|
|
this.isRepair,
|
|
packageNames.TIER_TWO
|
|
);
|
|
},
|
|
rearWiperApplicableForTierTwo() {
|
|
return shouldRearWipersBeAvailable(
|
|
this.glassToReplace,
|
|
this.nullSafeAvailableLineItems,
|
|
this.isRepair,
|
|
packageNames.TIER_TWO
|
|
);
|
|
},
|
|
frontWipersApplicableForTierThree() {
|
|
return shouldFrontWipersBeAvailable(
|
|
this.glassToReplace,
|
|
this.nullSafeAvailableLineItems,
|
|
this.isRepair,
|
|
packageNames.TIER_THREE
|
|
);
|
|
},
|
|
rearWiperApplicableForTierThree() {
|
|
return shouldRearWipersBeAvailable(
|
|
this.glassToReplace,
|
|
this.nullSafeAvailableLineItems,
|
|
this.isRepair,
|
|
packageNames.TIER_THREE
|
|
);
|
|
},
|
|
rainDefenseApplicableForTierThree() {
|
|
return shouldRainDefenseBeAvailable(
|
|
this.glassToReplace,
|
|
this.nullSafeAvailableLineItems,
|
|
this.isRepair,
|
|
packageNames.TIER_THREE
|
|
);
|
|
},
|
|
glassToReplace() {
|
|
return this.$store.getters.order.damage.glassToReplace;
|
|
},
|
|
isRepair() {
|
|
return this.$store.getters.order.damage.isRepair;
|
|
},
|
|
servicePackageDiscountParts() {
|
|
return findLineItemsWithPartType(
|
|
partTypeStrings.SERVICE_PACKAGE_DISCOUNT,
|
|
this.nullSafeAvailableLineItems
|
|
);
|
|
},
|
|
showRecalInServicePackages() {
|
|
return this.isRecalibrationOnOrder && !this.shouldHideRecalibration;
|
|
},
|
|
},
|
|
methods: {
|
|
processIfStatements,
|
|
hasPricingByDay() {
|
|
return experimentMixin.methods.hasSettingEqualTo(
|
|
experimentSettings.PRICING_BY_DAY,
|
|
"true"
|
|
);
|
|
},
|
|
getHeaderTextFromCms(cmsWidgetName) {
|
|
return this.getCmsContent(cmsWidgetName, "HeaderText");
|
|
},
|
|
getSubheaderTextFromCms(cmsWidgetName) {
|
|
return this.getCmsContent(cmsWidgetName, "SubheaderText");
|
|
},
|
|
getBodyTextFromCms(cmsWidgetName) {
|
|
const bodyText = this.getCmsContent(cmsWidgetName, "BodyText");
|
|
return this.processIfStatements(bodyText, "custom", this.getCustomValueFromString);
|
|
},
|
|
getFooterTextFromCms(cmsWidgetName) {
|
|
const footerText = this.getCmsContent(cmsWidgetName, "FooterText");
|
|
return this.processIfStatements(footerText, "custom", this.getCustomValueFromString);
|
|
},
|
|
getPackagePriceString(packageName) {
|
|
const formattedPriceFloat = parseFloat(
|
|
this.getPackagePrice(packageName, {
|
|
discountedPrice: false,
|
|
servicePackageDiscount: false,
|
|
})
|
|
).toFixed(2);
|
|
return "$" + formattedPriceFloat;
|
|
},
|
|
getDiscountedPackagePriceString(packageName, servicePackageDiscount) {
|
|
const formattedPriceFloat = parseFloat(
|
|
this.getPackagePrice(packageName, {
|
|
discountedPrice: true,
|
|
servicePackageDiscount,
|
|
})
|
|
).toFixed(2);
|
|
|
|
if (this.hasPricingByDay()) {
|
|
return "$" + formattedPriceFloat;
|
|
}
|
|
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
|
|
},
|
|
getPackagePrice(packageName, { discountedPrice = false, servicePackageDiscount = false }) {
|
|
let lineItemsToPrice = [...this.nullSafeAvailableLineItems];
|
|
|
|
if (this.isRecalibrationOnOrder && this.shouldHideRecalibration) {
|
|
lineItemsToPrice = getItemsWithoutRecalParts(lineItemsToPrice);
|
|
}
|
|
|
|
//remove service package discount part
|
|
if (this.isServicePackageDiscountOnOrder) {
|
|
lineItemsToPrice = lineItemsToPrice.filter((item) => {
|
|
return item.partType != this.servicePackageDiscountParts[0].partType;
|
|
});
|
|
}
|
|
|
|
if (discountedPrice) {
|
|
lineItemsToPrice.push(...removeVapsPromosFromPromoArray(this.activePromos));
|
|
}
|
|
if (servicePackageDiscount) {
|
|
lineItemsToPrice.push(...this.servicePackageDiscountParts);
|
|
}
|
|
let priceFloat = this.isInsuranceSelected
|
|
? 0
|
|
: baseMixin.methods.getTierOnePackagePrice(
|
|
baseMixin.methods.filterOutFees(lineItemsToPrice)
|
|
);
|
|
|
|
priceFloat += this.getVapsPrice(packageName, discountedPrice);
|
|
|
|
return priceFloat;
|
|
},
|
|
getServicePackageDiscountPrice() {
|
|
if (this.isServicePackageDiscountOnOrder) {
|
|
let price = 0;
|
|
price += baseMixin.methods.getTotalLineItemPrice(
|
|
this.servicePackageDiscountParts[0]
|
|
);
|
|
return Math.abs(price);
|
|
}
|
|
},
|
|
getVapsPrice(packageName, applyPromoDiscounts = false) {
|
|
const vapsItems = this.getVapsLineItemsForSelectedPackage(packageName);
|
|
let price = 0;
|
|
|
|
vapsItems.forEach((item) => {
|
|
price += baseMixin.methods.getTotalLineItemPrice(item);
|
|
});
|
|
|
|
if (applyPromoDiscounts && this.activePromos) {
|
|
const relevantPromos = getPromosThatMatchLineItemsOnOrder(
|
|
this.activePromos,
|
|
vapsItems
|
|
);
|
|
relevantPromos.forEach((promo) => {
|
|
price += baseMixin.methods.getTotalLineItemPrice(promo);
|
|
});
|
|
}
|
|
|
|
return price;
|
|
},
|
|
selectDefaultPackage() {
|
|
if (this.servicePackage != null) {
|
|
this.selectedPackageName = getPackageNameByType(this.servicePackage);
|
|
return;
|
|
}
|
|
const promosWithAddableVaps = getPromosWithAddableVaps(this.activePromos);
|
|
const vapsThatMatchPromos = getLineItemsThatMatchPromos(
|
|
promosWithAddableVaps,
|
|
this.nullSafeAvailableLineItems
|
|
);
|
|
const vapsFromStore = this.$store.getters.lineItems.vaps ?? [];
|
|
const vapsToUseForDefaultPackageSelection = this.combineLineItemsWithoutDuplicates(
|
|
vapsThatMatchPromos,
|
|
vapsFromStore
|
|
);
|
|
|
|
this.selectedPackageName = getHighestRequiredTier(
|
|
this.glassToReplace,
|
|
this.nullSafeAvailableLineItems,
|
|
this.isRepair,
|
|
vapsToUseForDefaultPackageSelection
|
|
);
|
|
},
|
|
getVapsLineItemsForSelectedPackage(packageName) {
|
|
const packageContentTypes = getPackageContents(
|
|
this.glassToReplace,
|
|
this.nullSafeAvailableLineItems,
|
|
this.isRepair,
|
|
packageName
|
|
);
|
|
|
|
let vapsLineItemsForSelectedPackage = [];
|
|
|
|
packageContentTypes.forEach((vapType) => {
|
|
vapsLineItemsForSelectedPackage.push(
|
|
...findLineItemsWithPartType(vapType, this.nullSafeAvailableLineItems)
|
|
);
|
|
});
|
|
|
|
return vapsLineItemsForSelectedPackage;
|
|
},
|
|
getServicePackageDiscountPartForSelectedPackage(packageName) {
|
|
const selectedPackage = this.servicePackageAnswers.filter(
|
|
(item) => item.value === packageName
|
|
);
|
|
if (selectedPackage?.[0]?.additionalButtonData?.servicePackageDiscount) {
|
|
return this.servicePackageDiscountParts;
|
|
} else return [];
|
|
},
|
|
combineLineItemsWithoutDuplicates(lineItemsOne, lineItemsTwo) {
|
|
const combinedLineItemArray = [...lineItemsTwo];
|
|
lineItemsOne.forEach((lineItemOne) => {
|
|
if (
|
|
!lineItemsTwo.filter((lineItemTwo) => lineItemTwo.id === lineItemOne.id).length
|
|
) {
|
|
combinedLineItemArray.push(lineItemOne);
|
|
}
|
|
});
|
|
return combinedLineItemArray;
|
|
},
|
|
getCustomValueFromString(str) {
|
|
switch (str) {
|
|
case "showRecalInServicePackages":
|
|
return this.showRecalInServicePackages;
|
|
case "frontWipersApplicableForTierTwo":
|
|
return this.frontWipersApplicableForTierTwo;
|
|
case "rearWiperApplicableForTierTwo":
|
|
return this.rearWiperApplicableForTierTwo;
|
|
case "frontWipersApplicableForTierThree":
|
|
return this.frontWipersApplicableForTierThree;
|
|
case "rearWiperApplicableForTierThree":
|
|
return this.rearWiperApplicableForTierThree;
|
|
case "rainDefenseApplicableForTierThree":
|
|
return this.rainDefenseApplicableForTierThree;
|
|
default:
|
|
return null;
|
|
}
|
|
},
|
|
},
|
|
components: {
|
|
buttonQuestion,
|
|
},
|
|
};
|
|
</script>
|