DigitalConsumer.FixMyGlass/src/layouts/quote/service-package-question/service-package-question.vue
Scott Kiener 291e13330d CSR-1520 | First integration of promo logic
Implementation of validate and revalidate endpoints in the store
Validate promo on quote via query string promo
Revalidate promos on quote page load
Remove promo query string on quote and payment-method forward navigation
Add in Id logic for all line items
Send relevant pricing data to service package question to be used later for UX changes
2023-10-12 12:03:02 -04:00

270 lines
9.9 KiB
Vue

<template>
<buttonQuestion
ref="buttonQuestion"
:answers="servicePackageAnswers"
:groupName="groupName"
buttonTypeString="servicePackageRadio"
:buttonTypeObject="servicePackageRadio"
v-model="selectedPackageName"
:validationRules="validationRules"
:isRequired="isRequired"
:logDisplayedValuesEvent="true" />
</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 { damageLocationsSelected as glassLocations } from "@/constants/damage-locations-selected";
import servicePackageRadio from "./service-package-radio/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,
} from "@/helpers/service-package-helper";
import {
getPromosThatMatchLineItemsOnOrder,
removeVapsPromosFromPromoArray,
} from "@/helpers/promotions-helper";
export default {
name: "servicePackageQuestion",
props: {
groupName: String,
cashCmsWidgetName: String,
insuranceCmsWidgetName: String,
validationRules: String,
isRequired: Boolean,
isInsuranceSelected: Boolean,
availableLineItems: null,
activePromos: null,
},
data() {
return {
servicePackageRadio: servicePackageRadio,
selectedPackageName: null,
};
},
watch: {
availableLineItems() {
if (this.$store.getters.payment.isInsurance != null) {
this.selectDefaultPackage();
}
},
selectedPackageName(newValue) {
const VapsProductsInSelectedPackage = this.getVapsLineItemsForSelectedPackage(newValue);
this.$emit("vapsItemsSelected", VapsProductsInSelectedPackage);
},
},
computed: {
nullSafeAvailableLineItems() {
return this.availableLineItems ?? [];
},
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),
buttonAuxillaryCopy: this.getDiscountedPackagePriceString(answer.Name),
buttonFooterCopy: this.getFooterTextFromCms(answer.SubWidgetName),
additionalButtonData: {
strikeThroughPrice: this.getPackagePriceString(answer.Name),
},
}));
return modifiedAnswers;
},
isRecalibrationOnOrder() {
return containsLineItemWithPartType(
partTypeStrings.RECALIBRATION,
this.nullSafeAvailableLineItems
);
},
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;
},
},
methods: {
processIfStatements,
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 })
).toFixed(2);
return "$" + formattedPriceFloat;
},
getDiscountedPackagePriceString(packageName) {
const formattedPriceFloat = parseFloat(
this.getPackagePrice(packageName, { discountedPrice: true })
).toFixed(2);
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
},
getPackagePrice(packageName, { discountedPrice = false }) {
const lineItemsToPrice = [...this.nullSafeAvailableLineItems];
if (discountedPrice) {
lineItemsToPrice.push(...removeVapsPromosFromPromoArray(this.activePromos));
}
let priceFloat = this.isInsuranceSelected
? 0
: baseMixin.methods.getTierOnePackagePrice(
baseMixin.methods.filterOutFees(lineItemsToPrice)
);
priceFloat += this.getVapsPrice(packageName, discountedPrice);
return priceFloat;
},
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() {
const vapsFromStore = this.$store.getters.lineItems.vaps ?? [];
this.selectedPackageName = getHighestRequiredTier(
this.glassToReplace,
this.nullSafeAvailableLineItems,
this.isRepair,
vapsFromStore
);
},
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;
},
getCustomValueFromString(str) {
switch (str) {
case "isRecalibrationOnOrder":
return this.isRecalibrationOnOrder;
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>