Watch lineItems to automatically run revalidate when the cart changes Add in auto add of addable vaps in beforeRouteEnter Create adding of addableVaps to order in promo helper
427 lines
17 KiB
Vue
427 lines
17 KiB
Vue
<template>
|
|
<transition name="fade" mode="out-in">
|
|
<div class="add-vaps-buttons" aria-live="polite">
|
|
<buttonQuestion
|
|
ref="buttonQuestion"
|
|
:answers="buttonsToDisplay"
|
|
groupName="addVaps"
|
|
v-model="buttonsToDisplay"
|
|
buttonTypeString="addVapsButton"
|
|
:buttonTypeObject="addVapsButton"
|
|
:isWide="buttonsToDisplay.length > 1 ? false : true"
|
|
@update:modelValue="openModal" />
|
|
|
|
<contentGroupModal
|
|
ref="RainDefenseModal"
|
|
cmsWidgetName="RainDefenseModal"
|
|
v-if="rainDefenseModal"
|
|
@footer-button-action="addRainDefenseToCart('RainDefenseModal', rainDefenseModal)"
|
|
footerButtonActionName="footer-button-action">
|
|
<p class="price">+${{ rainDefenseModal.listPrice }}</p>
|
|
</contentGroupModal>
|
|
|
|
<contentGroupModal
|
|
ref="WipersModal"
|
|
cmsWidgetName="WipersModal"
|
|
v-if="wipersModal"
|
|
@footer-button-action="addWipersToCart('WipersModal', wipersModal)"
|
|
footerButtonActionName="footer-button-action">
|
|
<div v-if="wipersOffered === wipersOfferedStrings.BOTH" class="wiper-options">
|
|
<buttonQuestion
|
|
ref="buttonQuestion"
|
|
buttonTypeString="checkbox"
|
|
class="mt-5"
|
|
:answers="wipersOptions"
|
|
groupName="wipers-options"
|
|
textPosition="text-center"
|
|
v-model="selectedWipers"
|
|
isMultiSelect
|
|
isRequired
|
|
validationRules="checkbox-required" />
|
|
</div>
|
|
<div v-else-if="wipersOffered === wipersOfferedStrings.FRONT" class="wiper-options">
|
|
<p class="price">+${{ wipersModal.totalFrontPrice }}</p>
|
|
</div>
|
|
<div v-else-if="wipersOffered === wipersOfferedStrings.REAR" class="wiper-options">
|
|
<p class="price">+${{ wipersModal.totalRearPrice }}</p>
|
|
</div>
|
|
</contentGroupModal>
|
|
</div>
|
|
</transition>
|
|
</template>
|
|
|
|
<script>
|
|
// COMPONENTS
|
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
|
import addVapsButton from "./add-vaps-button/add-vaps-button";
|
|
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
|
|
|
|
// SUPPORTING
|
|
import { partTypeStrings } from "@/constants/part-type-strings";
|
|
import { defineRule } from "vee-validate";
|
|
import { required } from "@/helpers/validation-rules";
|
|
import { errorMessages } from "@/constants/error-messages";
|
|
import { processIfStatements } from "@/helpers/cms-content-helper";
|
|
|
|
// DEFINE VALIDATION RULES
|
|
defineRule("checkbox-required", required(errorMessages.OPTION_REQUIRED));
|
|
|
|
const wipersOfferedStrings = {
|
|
FRONT: "FRONT",
|
|
REAR: "REAR",
|
|
BOTH: "BOTH",
|
|
};
|
|
|
|
export default {
|
|
name: "add-vaps-modal-buttons",
|
|
props: {
|
|
vapsTilesCmsName: String,
|
|
availableLineItems: Object,
|
|
modelValue: Object,
|
|
},
|
|
data() {
|
|
return {
|
|
addVapsButton: addVapsButton,
|
|
wipersOffered: null,
|
|
isModalOpened: false,
|
|
selectedWipers: this.getSelectedWipers(),
|
|
};
|
|
},
|
|
methods: {
|
|
processIfStatements,
|
|
openModal(modalName) {
|
|
this.selectedWipers = this.getSelectedWipers(); // reset selectedWipers to null upon modal open
|
|
this.$refs[modalName].openModal();
|
|
},
|
|
closeModal(modalName) {
|
|
this.$refs[modalName].closeModal();
|
|
},
|
|
addRainDefenseToCart(modalName, part) {
|
|
// Clone vaps array, then replace this.currentCartItems.vaps with it at the end
|
|
// in order to successfully trigger parent's watcher
|
|
const clonedVaps = this.currentCartItems.vaps.slice(0);
|
|
clonedVaps.push(part);
|
|
this.currentCartItems.vaps = clonedVaps;
|
|
this.closeModal(modalName);
|
|
const message = this.getRainDefenseAddedMessage();
|
|
this.$emit("added-to-cart", {
|
|
messageHeadline: message,
|
|
type: "alert-success",
|
|
isDismissible: true,
|
|
});
|
|
},
|
|
addWipersToCart(modalName, part) {
|
|
const itemsForCart = [];
|
|
|
|
const frontWipersAlreadyInCart = this.currentCartItems.vaps.some((item) => {
|
|
return item.partType === part.frontWiperLineItems[0].partType;
|
|
});
|
|
const rearWipersAlreadyInCart = this.currentCartItems.vaps.some((item) => {
|
|
return item.partType === part.rearWiperLineItems[0]?.partType;
|
|
});
|
|
|
|
if (this.wipersOffered === wipersOfferedStrings.BOTH) {
|
|
this.selectedWipers.forEach((wiper) => {
|
|
itemsForCart.push(wiper);
|
|
});
|
|
} else {
|
|
if (
|
|
!frontWipersAlreadyInCart &&
|
|
this.wipersOffered === wipersOfferedStrings.FRONT
|
|
) {
|
|
itemsForCart.push(wipersOfferedStrings.FRONT);
|
|
this.selectedWipers = ["FRONT"];
|
|
}
|
|
if (!rearWipersAlreadyInCart && this.wipersOffered === wipersOfferedStrings.REAR) {
|
|
itemsForCart.push(wipersOfferedStrings.REAR);
|
|
this.selectedWipers = ["REAR"];
|
|
}
|
|
}
|
|
// Clone vaps array, then replace this.currentCartItems.vaps with it at the end
|
|
// in order to successfully trigger parent's watcher
|
|
const clonedVaps = this.currentCartItems.vaps.slice(0);
|
|
|
|
itemsForCart.forEach((type) => {
|
|
if (type === wipersOfferedStrings.FRONT) {
|
|
part.frontWiperLineItems.forEach((part) => {
|
|
clonedVaps.push(part);
|
|
});
|
|
}
|
|
if (type === wipersOfferedStrings.REAR) {
|
|
part.rearWiperLineItems.forEach((part) => {
|
|
clonedVaps.push(part);
|
|
});
|
|
}
|
|
});
|
|
this.currentCartItems.vaps = clonedVaps;
|
|
|
|
this.closeModal(modalName);
|
|
|
|
const message = this.getWipersAddedMessage();
|
|
this.$emit("added-to-cart", {
|
|
messageHeadline: message,
|
|
type: "alert-success",
|
|
isDismissible: true,
|
|
});
|
|
},
|
|
updateWipersOffered(value) {
|
|
this.wipersOffered = value;
|
|
},
|
|
getSelectedWipers() {
|
|
return null;
|
|
},
|
|
getRainDefenseAddedMessage() {
|
|
return this.AddRainDefenseSuccessMessageFromCms;
|
|
},
|
|
getWipersAddedMessage() {
|
|
return this.processIfStatements(
|
|
this.AddWipersSuccessMessageFromCms,
|
|
"custom",
|
|
this.getCustomValueFromString
|
|
);
|
|
},
|
|
getCustomValueFromString(str) {
|
|
switch (str) {
|
|
case "vapsAddedIsFrontWipers":
|
|
return (
|
|
this.selectedWipers?.length === 1 &&
|
|
this.selectedWipers[0] === wipersOfferedStrings.FRONT
|
|
);
|
|
case "vapsAddedIsRearWipers":
|
|
return (
|
|
this.selectedWipers?.length === 1 &&
|
|
this.selectedWipers[0] === wipersOfferedStrings.REAR
|
|
);
|
|
case "vapsAddedIsBothWipers":
|
|
return this.selectedWipers?.length > 1;
|
|
default:
|
|
return null;
|
|
}
|
|
},
|
|
},
|
|
computed: {
|
|
currentCartItems() {
|
|
const modelValue = this.modelValue;
|
|
if (!modelValue.vaps) modelValue.vaps = [];
|
|
return modelValue;
|
|
},
|
|
rainDefenseModal() {
|
|
const lineItem = this.availableLineItems.find((item) => {
|
|
return item.partType === partTypeStrings.RAIN_DEFENSE;
|
|
});
|
|
if (lineItem)
|
|
lineItem.listPrice = parseFloat(
|
|
lineItem?.laborAmount + lineItem?.sellingPrice + lineItem?.kitPrice
|
|
).toFixed(2);
|
|
return lineItem;
|
|
},
|
|
wipersModal() {
|
|
// create a single wiper item for modal
|
|
const frontWiperLineItems = this.availableLineItems.filter((item) => {
|
|
return item.partType.includes(partTypeStrings.FRONT_WIPER);
|
|
});
|
|
const rearWiperLineItems = this.availableLineItems.filter((item) => {
|
|
return item.partType.includes(partTypeStrings.REAR_WIPER);
|
|
});
|
|
let wipersModal;
|
|
let totalFrontPrice = 0;
|
|
let totalRearPrice = 0;
|
|
|
|
// calculate prices to display
|
|
frontWiperLineItems?.forEach((item) => {
|
|
totalFrontPrice += item?.laborAmount + item?.sellingPrice + item?.kitPrice;
|
|
});
|
|
rearWiperLineItems?.forEach((item) => {
|
|
totalRearPrice += item?.laborAmount + item?.sellingPrice + item?.kitPrice;
|
|
});
|
|
|
|
wipersModal = {
|
|
description: "WIPERS ITEM",
|
|
partType: "WIPERS",
|
|
frontWiperLineItems: frontWiperLineItems,
|
|
rearWiperLineItems: rearWiperLineItems,
|
|
totalFrontPrice: parseFloat(totalFrontPrice).toFixed(2),
|
|
totalRearPrice: parseFloat(totalRearPrice).toFixed(2),
|
|
};
|
|
|
|
return wipersModal;
|
|
},
|
|
answersCmsData() {
|
|
return this.getCmsContent(this.vapsTilesCmsName, "Answers");
|
|
},
|
|
buttonsToDisplay() {
|
|
const buttons = [];
|
|
if (!this.answersCmsData) return buttons;
|
|
|
|
const rainDefenseInCart = this.currentCartItems.vaps?.some((vap) => {
|
|
return vap?.partType === partTypeStrings.RAIN_DEFENSE;
|
|
});
|
|
const frontWipersInCart = this.currentCartItems.vaps?.some((vap) => {
|
|
return vap?.partType?.includes(partTypeStrings.FRONT_WIPER);
|
|
});
|
|
const rearWipersInCart = this.currentCartItems.vaps?.some((vap) => {
|
|
return vap?.partType?.includes(partTypeStrings.REAR_WIPER);
|
|
});
|
|
|
|
const getAnswer = (name, answers) => {
|
|
const answerIndex = answers.findIndex((answer) => {
|
|
return answer.Name === name;
|
|
});
|
|
return answers[answerIndex];
|
|
};
|
|
|
|
if (!rainDefenseInCart) {
|
|
// NO RAIN DEFENSE IN CART; SHOW RAIN DEFENSE BUTTON
|
|
const modalData = getAnswer("RainDefenseModal", this.answersCmsData);
|
|
modalData.SubText = "+$" + this.rainDefenseModal?.listPrice;
|
|
buttons.push(modalData);
|
|
}
|
|
|
|
const modalData = getAnswer("WipersModal", this.answersCmsData);
|
|
if (!frontWipersInCart) {
|
|
if (!rearWipersInCart && this.wipersModal?.rearWiperLineItems.length > 0) {
|
|
// NO REAR WIPERS or FRONT WIPERS IN CART; SHOW COMBO BUTTON
|
|
const prices = [
|
|
this.wipersModal?.totalFrontPrice,
|
|
this.wipersModal?.totalRearPrice,
|
|
];
|
|
prices.sort((a, b) => a - b);
|
|
modalData.SubText = "+$" + prices[0] + " - $" + prices[prices.length - 1];
|
|
this.updateWipersOffered(wipersOfferedStrings.BOTH);
|
|
buttons.push(modalData);
|
|
} else {
|
|
// NO FRONT WIPERS IN CART; SHOW ONLY FRONT WIPERS BUTTON
|
|
modalData.SubText = "+$" + this.wipersModal?.totalFrontPrice;
|
|
this.updateWipersOffered(wipersOfferedStrings.FRONT);
|
|
buttons.push(modalData);
|
|
}
|
|
} else if (!rearWipersInCart && this.wipersModal?.rearWiperLineItems.length > 0) {
|
|
// NO REAR WIPERS IN CART; SHOW ONLY REAR WIPERS BUTTON
|
|
modalData.SubText = "+$" + this.wipersModal?.totalRearPrice;
|
|
this.updateWipersOffered(wipersOfferedStrings.REAR);
|
|
buttons.push(modalData);
|
|
}
|
|
|
|
return buttons;
|
|
},
|
|
wipersOfferedStrings() {
|
|
return wipersOfferedStrings;
|
|
},
|
|
wipersOptions() {
|
|
const wipersOptions = [];
|
|
const wipersFrontCopy = this.getCmsContent(
|
|
"AddFrontBladesQuestionWidget",
|
|
"QuestionText"
|
|
);
|
|
const wipersRearCopy = this.getCmsContent(
|
|
"AddRearBladesQuestionWidget",
|
|
"QuestionText"
|
|
);
|
|
const frontWipersLineItems = this.wipersModal.frontWiperLineItems;
|
|
const rearWipersLineItems = this.wipersModal.rearWiperLineItems;
|
|
|
|
if (frontWipersLineItems) {
|
|
const wipersOption = {
|
|
buttonLabel: wipersFrontCopy,
|
|
groupName: "wipers-options",
|
|
value: wipersOfferedStrings.FRONT,
|
|
buttonLabelSubCopy: "buttonLabelSubCopy",
|
|
buttonBodyCopy: "buttonBodyCopy",
|
|
buttonAuxillaryCopy: "buttonAuxillaryCopy",
|
|
buttonFooterCopy: "buttonFooterCopy",
|
|
additionalButtonData: "+$" + this.wipersModal.totalFrontPrice,
|
|
};
|
|
wipersOptions.push(wipersOption);
|
|
}
|
|
if (rearWipersLineItems) {
|
|
const wipersOption = {
|
|
buttonLabel: wipersRearCopy,
|
|
groupName: "wipers-options",
|
|
value: wipersOfferedStrings.REAR,
|
|
buttonLabelSubCopy: "buttonLabelSubCopy",
|
|
buttonBodyCopy: "buttonBodyCopy",
|
|
buttonAuxillaryCopy: "buttonAuxillaryCopy",
|
|
buttonFooterCopy: "buttonFooterCopy",
|
|
additionalButtonData: "+$" + this.wipersModal.totalRearPrice,
|
|
};
|
|
wipersOptions.push(wipersOption);
|
|
}
|
|
|
|
return wipersOptions;
|
|
},
|
|
AddRainDefenseSuccessMessageFromCms() {
|
|
return this.getCmsContent("AddRainDefenseSuccessMessageWidget", "Text");
|
|
},
|
|
AddWipersSuccessMessageFromCms() {
|
|
return this.getCmsContent("AddWipersSuccessMessageWidget", "Text");
|
|
},
|
|
},
|
|
components: {
|
|
buttonQuestion,
|
|
contentGroupModal,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.add-vaps-buttons {
|
|
// necessary overrides for modals
|
|
.modal {
|
|
&.modal-component {
|
|
.modal-dialog {
|
|
.modal-content {
|
|
.modal-body {
|
|
padding-bottom: 1.5rem;
|
|
|
|
& > img {
|
|
margin-bottom: 1.5rem;
|
|
line-height: 2;
|
|
text-align: center;
|
|
}
|
|
& > h5 {
|
|
text-align: center;
|
|
}
|
|
p {
|
|
margin-bottom: 1rem;
|
|
}
|
|
p.subheader-text {
|
|
text-align: center;
|
|
}
|
|
p.price {
|
|
text-align: center;
|
|
}
|
|
.wiper-options {
|
|
.ui-checkbox {
|
|
display: block;
|
|
|
|
& > div.col {
|
|
margin-bottom: 1rem;
|
|
|
|
&:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
}
|
|
.checkbox {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
|
|
.additional-button-data {
|
|
font-size: 0.875rem;
|
|
line-height: 1.75;
|
|
padding-left: 0.5rem;
|
|
color: $green;
|
|
}
|
|
}
|
|
}
|
|
p {
|
|
margin-bottom: 0;
|
|
line-height: 1.75;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|