Merge pull request #1259 from Safelite/feature/CSR-1370

Feature/csr 1370
This commit is contained in:
chloeherdsafelite 2023-07-20 15:10:24 -04:00 committed by GitHub
commit efc21e118f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 2506 additions and 188 deletions

View file

@ -0,0 +1,5 @@
export const packageNames = {
TIER_ONE: "TierOne",
TIER_TWO: "TierTwo",
TIER_THREE: "TierThree",
};

View file

@ -0,0 +1,239 @@
import { partTypeStrings } from "@/constants/part-type-strings";
import { damageLocationsSelected as glassLocations } from "@/constants/damage-locations-selected";
import { packageNames } from "@/constants/package-names";
export function containsLineItemWithPartType(typeToFind, itemsToSearch) {
const partTypeMatches = findLineItemsWithPartType(typeToFind, itemsToSearch);
return !!partTypeMatches?.length;
}
export function findLineItemsWithPartType(typeToFind, itemsToSearch) {
const partTypeMatches = itemsToSearch?.filter(
(lineItem) => lineItem.partType.toUpperCase() === typeToFind.toUpperCase()
);
return partTypeMatches;
}
export function getVapsLineItems(availableLineItems, vapTypes) {
let lineItems = [];
for (let i = 0; i < vapTypes.length; i++) {
lineItems.push(...findLineItemsWithPartType(vapTypes[i], availableLineItems));
}
return lineItems;
}
export function containsGlassPieceWithLocation(locationToFind, glassPiecesToSearch) {
const glassLocationMatches = glassPiecesToSearch?.filter(
(glassPiece) => glassPiece.glassLocation.toUpperCase() === locationToFind.toUpperCase()
);
return !!glassLocationMatches?.length;
}
export function getAvailablePackages(glassToReplace, availableLineItems, isRepair) {
let tierOneVaps = getPackageContents(
glassToReplace,
availableLineItems,
isRepair,
packageNames.TIER_ONE
);
let tierTwoVaps = getPackageContents(
glassToReplace,
availableLineItems,
isRepair,
packageNames.TIER_TWO
);
let tierThreeVaps = getPackageContents(
glassToReplace,
availableLineItems,
isRepair,
packageNames.TIER_THREE
);
if (tierTwoVaps.length === 0) {
return [
{
packageName: packageNames.TIER_ONE,
vapTypes: tierOneVaps,
},
{
packageName: packageNames.TIER_THREE,
vapTypes: tierThreeVaps,
},
];
} else {
return [
{
packageName: packageNames.TIER_ONE,
vapTypes: tierOneVaps,
},
{
packageName: packageNames.TIER_TWO,
vapTypes: tierTwoVaps,
},
{
packageName: packageNames.TIER_THREE,
vapTypes: tierThreeVaps,
},
];
}
}
export function getPackageContents(glassToReplace, availableLineItems, isRepair, targetTier) {
let vaps = [];
if (shouldFrontWipersBeAvailable(glassToReplace, availableLineItems, isRepair, targetTier)) {
vaps.push(partTypeStrings.FRONT_WIPER);
}
if (shouldRearWipersBeAvailable(glassToReplace, availableLineItems, isRepair, targetTier)) {
vaps.push(partTypeStrings.REAR_WIPER);
}
if (shouldRainDefenseBeAvailable(glassToReplace, availableLineItems, isRepair, targetTier)) {
vaps.push(partTypeStrings.RAIN_DEFENSE);
}
return vaps;
}
export function shouldFrontWipersBeAvailable(
glassToReplace,
availableLineItems,
isRepair,
targetTier
) {
const frontWiperIsAvailable = containsLineItemWithPartType(
partTypeStrings.FRONT_WIPER,
availableLineItems
);
const isFrontWindshieldTask =
isRepair || containsGlassPieceWithLocation(glassLocations.WINDSHIELD, glassToReplace);
switch (targetTier) {
case packageNames.TIER_TWO:
return frontWiperIsAvailable && isFrontWindshieldTask;
case packageNames.TIER_THREE:
return frontWiperIsAvailable;
default:
return false;
}
}
export function shouldRearWipersBeAvailable(
glassToReplace,
availableLineItems,
isRepair,
targetTier
) {
const rearWiperIsAvailable = containsLineItemWithPartType(
partTypeStrings.REAR_WIPER,
availableLineItems
);
const frontWiperIsAvailable = containsLineItemWithPartType(
partTypeStrings.FRONT_WIPER,
availableLineItems
);
const isRearWindshieldTask = containsGlassPieceWithLocation(
glassLocations.REAR,
glassToReplace
);
switch (targetTier) {
case packageNames.TIER_TWO:
return rearWiperIsAvailable && isRearWindshieldTask;
case packageNames.TIER_THREE:
return rearWiperIsAvailable && (isRearWindshieldTask || !frontWiperIsAvailable);
default:
return false;
}
}
export function shouldRainDefenseBeAvailable(
glassToReplace,
availableLineItems,
isRepair,
targetTier
) {
const isTierThree = targetTier === packageNames.TIER_THREE;
const frontWipersInTierTwo = shouldFrontWipersBeAvailable(
glassToReplace,
availableLineItems,
isRepair,
packageNames.TIER_TWO
);
const frontWipersInTierThree = shouldFrontWipersBeAvailable(
glassToReplace,
availableLineItems,
isRepair,
packageNames.TIER_THREE
);
const rearWipersInTierTwo = shouldRearWipersBeAvailable(
glassToReplace,
availableLineItems,
isRepair,
packageNames.TIER_TWO
);
return isTierThree && !(rearWipersInTierTwo && !frontWipersInTierTwo && frontWipersInTierThree);
}
export function getLowestTierForType(glassToReplace, availableLineItems, isRepair, partType) {
const packages = getAvailablePackages(glassToReplace, availableLineItems, isRepair);
for (let i = 0; i < packages.length; i++) {
for (let j = 0; j < packages[i].vapTypes.length; j++) {
if (packages[i].vapTypes[j].toUpperCase() === partType.toUpperCase()) {
return packages[i].packageName;
}
}
}
return packageNames.TIER_ONE;
}
export function getHighestRequiredTier(glassToReplace, availableLineItems, isRepair, vaps) {
let currentHighestTier = packageNames.TIER_ONE;
for (let i = 0; i < vaps.length; i++) {
const lowestTierForItem = getLowestTierForType(
glassToReplace,
availableLineItems,
isRepair,
vaps[i].partType
);
currentHighestTier = maxTier(currentHighestTier, lowestTierForItem);
}
return currentHighestTier;
}
export function getHighestFullySatisfiedTier(glassToReplace, availableLineItems, isRepair, vaps) {
const packages = getAvailablePackages(glassToReplace, availableLineItems, isRepair);
let highestSatisfiedPackage = packageNames.TIER_ONE;
for (let i = 0; i < packages.length; i++) {
let isPackageSatisfied = true;
for (let j = 0; j < packages[i].vapTypes.length; j++) {
isPackageSatisfied =
isPackageSatisfied && containsLineItemWithPartType(packages[i].vapTypes[j], vaps);
}
if (isPackageSatisfied) {
highestSatisfiedPackage = packages[i].packageName;
}
}
return highestSatisfiedPackage;
}
function maxTier(tierA, tierB) {
if (tierA === packageNames.TIER_THREE || tierB === packageNames.TIER_THREE) {
return packageNames.TIER_THREE;
}
if (tierA === packageNames.TIER_TWO || tierB === packageNames.TIER_TWO) {
return packageNames.TIER_TWO;
}
return packageNames.TIER_ONE;
}

File diff suppressed because it is too large Load diff

View file

@ -18,12 +18,17 @@ 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";
const packageNames = {
TIER_ONE: "TierOne",
TIER_TWO: "TierTwo",
TIER_THREE: "TierThree",
};
import { packageNames } from "@/constants/package-names";
import {
shouldFrontWipersBeAvailable,
shouldRearWipersBeAvailable,
shouldRainDefenseBeAvailable,
getAvailablePackages,
getHighestRequiredTier,
getPackageContents,
containsLineItemWithPartType,
findLineItemsWithPartType,
} from "@/helpers/service-package-helper";
export default {
name: "servicePackageQuestion",
@ -65,11 +70,17 @@ export default {
if (!cmsAnswersContent) {
return null;
}
if (!this.shouldDisplayTierTwoPackage) {
cmsAnswersContent = cmsAnswersContent.filter(
(answer) => answer.Name != packageNames.TIER_TWO
);
}
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),
@ -81,67 +92,56 @@ export default {
return modifiedAnswers;
},
isRecalibrationOnOrder() {
return this.lineItemsContainsPartType(partTypeStrings.RECALIBRATION);
return containsLineItemWithPartType(
partTypeStrings.RECALIBRATION,
this.nullSafeAvailableLineItems
);
},
frontWipersApplicableForTierTwo() {
const frontWipersAreAvailable = this.lineItemsContainsPartType(
partTypeStrings.FRONT_WIPER
return shouldFrontWipersBeAvailable(
this.glassToReplace,
this.nullSafeAvailableLineItems,
this.isRepair,
packageNames.TIER_TWO
);
const isRepair = this.$store.getters.order.damage.isRepair;
const glassToReplaceContainsWindshield = this.glassToReplaceContainsGlassLocation(
glassLocations.WINDSHIELD
);
if (frontWipersAreAvailable) {
if (isRepair) {
return true;
} else {
if (glassToReplaceContainsWindshield) {
return true;
} else {
return false;
}
}
} else {
return false;
}
},
rearWiperApplicableForTierTwo() {
const rearWiperIsAvailable = this.lineItemsContainsPartType(partTypeStrings.REAR_WIPER);
return (
this.glassToReplaceContainsGlassLocation(glassLocations.REAR) &&
rearWiperIsAvailable
return shouldRearWipersBeAvailable(
this.glassToReplace,
this.nullSafeAvailableLineItems,
this.isRepair,
packageNames.TIER_TWO
);
},
frontWipersApplicableForTierThree() {
const frontWipersAreAvailable = this.lineItemsContainsPartType(
partTypeStrings.FRONT_WIPER
return shouldFrontWipersBeAvailable(
this.glassToReplace,
this.nullSafeAvailableLineItems,
this.isRepair,
packageNames.TIER_THREE
);
return frontWipersAreAvailable;
},
rearWiperApplicableForTierThree() {
const rearWiperIsAvailable = this.lineItemsContainsPartType(partTypeStrings.REAR_WIPER);
const frontWipersAreAvailable = this.lineItemsContainsPartType(
partTypeStrings.FRONT_WIPER
);
return (
rearWiperIsAvailable &&
(this.glassToReplaceContainsGlassLocation(glassLocations.REAR) ||
!frontWipersAreAvailable)
return shouldRearWipersBeAvailable(
this.glassToReplace,
this.nullSafeAvailableLineItems,
this.isRepair,
packageNames.TIER_THREE
);
},
rainDefenseApplicableForTierThree() {
if (
this.rearWiperApplicableForTierTwo &&
!this.frontWipersApplicableForTierTwo &&
this.frontWipersApplicableForTierThree
) {
return false;
} else {
return true;
}
return shouldRainDefenseBeAvailable(
this.glassToReplace,
this.nullSafeAvailableLineItems,
this.isRepair,
packageNames.TIER_THREE
);
},
shouldDisplayTierTwoPackage() {
return this.frontWipersApplicableForTierTwo || this.rearWiperApplicableForTierTwo;
glassToReplace() {
return this.$store.getters.order.damage.glassToReplace;
},
isRepair() {
return this.$store.getters.order.damage.isRepair;
},
},
methods: {
@ -170,65 +170,31 @@ export default {
: baseMixin.methods.getTierOnePackagePrice(
baseMixin.methods.filterOutFees(this.nullSafeAvailableLineItems)
);
if (packageName === packageNames.TIER_TWO) {
priceFloat += this.getTierTwoPackageVapsPrice();
} else if (packageName === packageNames.TIER_THREE) {
priceFloat += this.getTierThreePackageVapsPrice();
}
priceFloat += this.getVapsPrice(packageName);
return priceFloat;
},
getTierTwoPackageVapsPrice() {
let vapsPrice = 0;
const priceFrontWipers = this.frontWipersApplicableForTierTwo;
const priceRearWipers = this.rearWiperApplicableForTierTwo;
this.nullSafeAvailableLineItems.forEach((item) => {
if (
(priceFrontWipers &&
item.partType.toUpperCase() === partTypeStrings.FRONT_WIPER) ||
(priceRearWipers && item.partType.toUpperCase() === partTypeStrings.REAR_WIPER)
) {
vapsPrice += baseMixin.methods.getTotalLineItemPrice(item);
}
getVapsPrice(packageName) {
const vapsItems = this.getVapsLineItemsForSelectedPackage(packageName);
let price = 0;
vapsItems.forEach((item) => {
price += baseMixin.methods.getTotalLineItemPrice(item);
});
return vapsPrice;
},
getTierThreePackageVapsPrice() {
let vapsPrice = 0;
const priceFrontWipers = this.frontWipersApplicableForTierThree;
const priceRearWipers = this.rearWiperApplicableForTierThree;
const priceRainDefense = this.rainDefenseApplicableForTierThree;
this.nullSafeAvailableLineItems.forEach((item) => {
if (
(priceFrontWipers &&
item.partType.toUpperCase() === partTypeStrings.FRONT_WIPER) ||
(priceRearWipers &&
item.partType.toUpperCase() === partTypeStrings.REAR_WIPER) ||
(priceRainDefense &&
item.partType.toUpperCase() === partTypeStrings.RAIN_DEFENSE)
) {
vapsPrice += baseMixin.methods.getTotalLineItemPrice(item);
}
});
return vapsPrice;
return price;
},
selectDefaultPackage() {
const vapsFromStore = this.$store.getters.lineItems.vaps;
let lowestTierForPackage = packageNames.TIER_ONE;
if (vapsFromStore?.length > 0) {
vapsFromStore.every((vapsItem) => {
let lowestTierForThisItem = this.getLowestTierForThisItem(vapsItem);
if (lowestTierForThisItem === packageNames.TIER_THREE) {
lowestTierForPackage = packageNames.TIER_THREE;
return false;
} else if (lowestTierForThisItem === packageNames.TIER_TWO) {
lowestTierForPackage = packageNames.TIER_TWO;
return true;
} else {
return true;
}
});
}
this.selectedPackageName = lowestTierForPackage;
const vapsFromStore = this.$store.getters.lineItems.vaps ?? [];
this.selectedPackageName = getHighestRequiredTier(
this.glassToReplace,
this.nullSafeAvailableLineItems,
this.isRepair,
vapsFromStore
);
},
allGlassPartsAndSupportingItemsHavePrices(lineItems) {
if (lineItems?.glassParts) {
@ -254,63 +220,22 @@ export default {
(lineItem.sellingPrice == null || lineItem.sellingPrice == 0)
);
},
getLowestTierForThisItem(vapsItem) {
let lowestTierForThisItem = null;
switch (vapsItem.partType) {
case partTypeStrings.FRONT_WIPER:
if (this.frontWipersApplicableForTierThree) {
lowestTierForThisItem = packageNames.TIER_THREE;
}
if (this.frontWipersApplicableForTierTwo) {
lowestTierForThisItem = packageNames.TIER_TWO;
}
break;
case partTypeStrings.REAR_WIPER:
if (this.rearWiperApplicableForTierThree) {
lowestTierForThisItem = packageNames.TIER_THREE;
}
if (this.rearWiperApplicableForTierTwo) {
lowestTierForThisItem = packageNames.TIER_TWO;
}
break;
case partTypeStrings.RAIN_DEFENSE:
if (this.rainDefenseApplicableForTierThree) {
lowestTierForThisItem = packageNames.TIER_THREE;
}
break;
}
return lowestTierForThisItem;
},
getVapsLineItemsForSelectedPackage(packageName) {
const vapsLineItemsForSelectedPackage = [];
if (packageName === packageNames.TIER_TWO) {
if (this.frontWipersApplicableForTierTwo) {
vapsLineItemsForSelectedPackage.push(
...this.getLineItemsContainingPartType(partTypeStrings.FRONT_WIPER)
);
}
if (this.rearWiperApplicableForTierTwo) {
vapsLineItemsForSelectedPackage.push(
...this.getLineItemsContainingPartType(partTypeStrings.REAR_WIPER)
);
}
} else if (packageName === packageNames.TIER_THREE) {
if (this.frontWipersApplicableForTierThree) {
vapsLineItemsForSelectedPackage.push(
...this.getLineItemsContainingPartType(partTypeStrings.FRONT_WIPER)
);
}
if (this.rearWiperApplicableForTierThree) {
vapsLineItemsForSelectedPackage.push(
...this.getLineItemsContainingPartType(partTypeStrings.REAR_WIPER)
);
}
if (this.rainDefenseApplicableForTierThree) {
vapsLineItemsForSelectedPackage.push(
...this.getLineItemsContainingPartType(partTypeStrings.RAIN_DEFENSE)
);
}
}
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) {
@ -331,23 +256,6 @@ export default {
return null;
}
},
getLineItemsContainingPartType(partType) {
const partTypeMatches = this.nullSafeAvailableLineItems.filter(
(lineItem) => lineItem.partType.toUpperCase() === partType
);
return partTypeMatches;
},
lineItemsContainsPartType(partType) {
const partTypeMatches = this.getLineItemsContainingPartType(partType);
return !!partTypeMatches.length;
},
glassToReplaceContainsGlassLocation(glassLocation) {
const glassLocationMatches =
this.$store.getters.order.damage.glassToReplace?.filter(
(glassToReplace) => glassToReplace.glassLocation === glassLocation
) ?? [];
return !!glassLocationMatches.length;
},
},
components: {
buttonQuestion,

View file

@ -5,7 +5,12 @@
:cmsWidgetName="headerCmsWidgetName"
typeStyle="body small bold dark"
margin="mt-0" />
<textLink linkType="textSmall" text="Edit" class="ml-auto" @click-event="linkClicked" />
<textLink
linkType="textSmall"
text="Edit"
class="ml-auto"
@click-event="linkClicked"
href="javascript:void(0)" />
</div>
<div class="small" v-for="item in content" :key="item" data-test="contentLine">
{{ item }}

View file

@ -0,0 +1,969 @@
import { shallowMount } from "@vue/test-utils";
import { getMountOptions } from "@/helpers/unit-test-helper.js";
import servicePackageReview from "@/layouts/review/review-sections/service-package-review/service-package-review";
import { packageNames } from "@/constants/package-names";
import { partTypeStrings } from "@/constants/part-type-strings";
import { damageLocationsSelected as glassConstants } from "@/constants/damage-locations-selected";
const testConstants = {
cmsPropValues: {
servicePackageOptionsCmsName: "ServicePackageTitle",
defaultPackageItemsCmsName: "DefaultPackageItemDescriptions",
vapsItemsCmsName: "VapsItemDescriptions",
},
widgetNames: {
tierOneTitle: "EconomyServiceTitle",
tierTwoTitle: "StandardServiceTitle",
tierThreeTitle: "PremiumServiceTitle",
},
defaultItemCopy: {
itemOne: "Item Description 1",
itemTwo: "Item Description 2",
itemThree: "Item Description 3",
itemFour: "Item Description 4",
defaultItemCopyArray: ["Item Description 1", "Item Description 2", "Item Description 3"],
},
vapsCopy: {
frontWiperCopy: "Front Wiper copy",
rearWiperCopy: "Rear Wiper copy",
rainDefenseCopy: "Rain defense copy",
},
parts: {
frontWiperPart: {
partNumber: "SBB16",
description: "SAFELITE BEAM BLADE 16",
partType: "FRONT WIPER",
price: 32.64,
},
rearWiperPart: {
partNumber: "SBBR12A",
description: "SAFELITE REAR BLADE 12A",
partType: "REAR WIPER",
price: 24.48,
},
rainDefensePart: {
partNumber: "RAIN DEFENSE",
description: null,
partType: "RAIN DEFENSE",
price: 35.5,
},
recalPart: {
partNumber: "RECAL STATIC",
Description: "Recalibration",
partType: "recalibration",
Quantity: "1",
price: 150.0,
},
},
damages: {
frontWindshield: {
glassLocation: glassConstants.WINDSHIELD,
glassName: glassConstants.SINGLE,
},
rearWindshield: {
glassLocation: glassConstants.REAR,
glassName: glassConstants.STATIONARY,
},
sideGlass: {
glassLocation: glassConstants.PASSENGER,
glassName: glassConstants.QUARTER,
},
},
imageId: "00000000-0000-0000-0000-000000000000",
};
const figmaScenarios = [
{
name: "05_01_CSR_Quote_Cash",
params: {
availableVaps: [
testConstants.parts.frontWiperPart,
testConstants.parts.rearWiperPart,
testConstants.parts.rainDefensePart,
],
damage: {
isRepair: false,
glassToReplace: [testConstants.damages.frontWindshield],
},
glassParts: [],
supportingItems: [],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Standard",
vapsCombo: [testConstants.parts.frontWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
],
},
},
{
name: "Premium",
vapsCombo: [
testConstants.parts.rainDefensePart,
testConstants.parts.frontWiperPart,
],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Standard+RearWiper",
vapsCombo: [testConstants.parts.frontWiperPart, testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
],
},
// 05_01_CSR_Quote_Standard_Repair & 05_01_CSR_Quote_Recal have identical outcomes to above, but included in case that changes in the future.
{
name: "05_01_CSR_Quote_Standard_Repair",
params: {
availableVaps: [
testConstants.parts.frontWiperPart,
testConstants.parts.rearWiperPart,
testConstants.parts.rainDefensePart,
],
damage: {
isRepair: true,
glassToReplace: [],
},
glassParts: [],
supportingItems: [],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Standard",
vapsCombo: [testConstants.parts.frontWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
],
},
},
{
name: "Premium",
vapsCombo: [
testConstants.parts.rainDefensePart,
testConstants.parts.frontWiperPart,
],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Standard+RearWiper",
vapsCombo: [testConstants.parts.frontWiperPart, testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
],
},
{
name: "05_01_CSR_Quote_Recal",
params: {
availableVaps: [
testConstants.parts.frontWiperPart,
testConstants.parts.rearWiperPart,
testConstants.parts.rainDefensePart,
],
damage: {
isRepair: false,
glassToReplace: [testConstants.damages.frontWindshield],
},
glassParts: [],
supportingItems: [testConstants.parts.recalPart],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Standard",
vapsCombo: [testConstants.parts.frontWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
],
},
},
{
name: "Premium",
vapsCombo: [
testConstants.parts.rainDefensePart,
testConstants.parts.frontWiperPart,
],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Standard+RearWiper",
vapsCombo: [testConstants.parts.frontWiperPart, testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
],
},
// 05_01_CSR_Quote_RearGlass omitted as a duplicate of below.
{
name: "05_01_CSR_Quote_RearGlass+NonWindshield",
params: {
availableVaps: [
testConstants.parts.frontWiperPart,
testConstants.parts.rearWiperPart,
testConstants.parts.rainDefensePart,
],
damage: {
isRepair: false,
glassToReplace: [testConstants.damages.rearWindshield],
},
glassParts: [],
supportingItems: [],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Economy+Frontwiper",
vapsCombo: [testConstants.parts.frontWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
],
},
},
{
name: "Standard",
vapsCombo: [testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
{
name: "Standard+RainDefense",
vapsCombo: [testConstants.parts.rearWiperPart, testConstants.parts.rainDefensePart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rearWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Premium",
vapsCombo: [testConstants.parts.rearWiperPart, testConstants.parts.frontWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
],
},
{
name: "05_01_CSR_Quote_RearGlass+Windshield",
params: {
availableVaps: [
testConstants.parts.frontWiperPart,
testConstants.parts.rearWiperPart,
testConstants.parts.rainDefensePart,
],
damage: {
isRepair: false,
glassToReplace: [
testConstants.damages.frontWindshield,
testConstants.damages.rearWindshield,
],
},
glassParts: [],
supportingItems: [],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Economy+Frontwiper",
vapsCombo: [testConstants.parts.frontWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
],
},
},
{
name: "Economy+Rearwiper",
vapsCombo: [testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
{
name: "Economy+RainDefense",
vapsCombo: [testConstants.parts.rainDefensePart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Economy+Frontwiper+RainDefense",
vapsCombo: [
testConstants.parts.frontWiperPart,
testConstants.parts.rainDefensePart,
],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Economy+Rearwiper+RainDefense",
vapsCombo: [testConstants.parts.rearWiperPart, testConstants.parts.rainDefensePart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rearWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Standard",
vapsCombo: [testConstants.parts.frontWiperPart, testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
{
name: "Premium",
vapsCombo: [
testConstants.parts.rearWiperPart,
testConstants.parts.frontWiperPart,
testConstants.parts.rainDefensePart,
],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rearWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
],
},
{
name: "05_01_CSR_Quote_RearGlassNoFrontFit",
params: {
availableVaps: [testConstants.parts.rearWiperPart, testConstants.parts.rainDefensePart],
damage: {
isRepair: false,
glassToReplace: [testConstants.damages.rearWindshield],
},
glassParts: [],
supportingItems: [],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Economy+Raindefense",
vapsCombo: [testConstants.parts.rainDefensePart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Standard",
vapsCombo: [testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
{
name: "Premium",
vapsCombo: [testConstants.parts.rearWiperPart, testConstants.parts.rainDefensePart],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rearWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
],
},
// 05_01_CSR_Quote_Windshield+SideGlass has identical outcomes to 05_01_CSR_Quote_Cash, but included in case that changes in the future.
{
name: "05_01_CSR_Quote_Windshield+SideGlass",
params: {
availableVaps: [
testConstants.parts.frontWiperPart,
testConstants.parts.rearWiperPart,
testConstants.parts.rainDefensePart,
],
damage: {
isRepair: false,
glassToReplace: [
testConstants.damages.frontWindshield,
testConstants.damages.sideGlass,
],
},
glassParts: [],
supportingItems: [],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Standard",
vapsCombo: [testConstants.parts.frontWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
],
},
},
{
name: "Premium",
vapsCombo: [
testConstants.parts.rainDefensePart,
testConstants.parts.frontWiperPart,
],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Standard+RearWiper",
vapsCombo: [testConstants.parts.frontWiperPart, testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierTwoTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
],
},
// Has no standard package
{
name: "05_01_CSR_Quote_SideGlass",
params: {
availableVaps: [
testConstants.parts.frontWiperPart,
testConstants.parts.rearWiperPart,
testConstants.parts.rainDefensePart,
],
damage: {
isRepair: false,
glassToReplace: [testConstants.damages.sideGlass],
},
glassParts: [],
supportingItems: [],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Economy+Frontwiper",
vapsCombo: [testConstants.parts.frontWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
],
},
},
{
name: "Economy+RainDefense",
vapsCombo: [testConstants.parts.rainDefensePart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Economy+Rearwiper",
vapsCombo: [testConstants.parts.rearWiperPart],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rearWiperCopy,
],
},
},
{
name: "Premium",
vapsCombo: [
testConstants.parts.rainDefensePart,
testConstants.parts.frontWiperPart,
],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
{
name: "Premium+Rearwiper",
vapsCombo: [
testConstants.parts.rainDefensePart,
testConstants.parts.frontWiperPart,
testConstants.parts.rearWiperPart,
],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.frontWiperCopy,
testConstants.vapsCopy.rearWiperCopy,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
],
},
// Has no standard package
{
name: "05_01_CSR_Quote_NoWiperFit",
params: {
availableVaps: [testConstants.parts.rainDefensePart],
damage: {
isRepair: false,
glassToReplace: [testConstants.damages.frontWindshield],
},
glassParts: [],
supportingItems: [],
},
iterations: [
{
name: "Economy",
vapsCombo: [],
expected: {
packageNameWidget: testConstants.widgetNames.tierOneTitle,
displayContent: testConstants.defaultItemCopy.defaultItemCopyArray,
},
},
{
name: "Premium",
vapsCombo: [testConstants.parts.rainDefensePart],
expected: {
packageNameWidget: testConstants.widgetNames.tierThreeTitle,
displayContent: [
...testConstants.defaultItemCopy.defaultItemCopyArray,
testConstants.vapsCopy.rainDefenseCopy,
],
},
},
],
},
];
let cmsContent;
describe("Service Package Review Block", () => {
beforeEach(() => {
cmsContent = {
ServicePackageTitle: {
Answers: [
{
Name: packageNames.TIER_ONE,
Text: "",
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: testConstants.widgetNames.tierOneTitle,
},
{
Name: packageNames.TIER_TWO,
Text: "",
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: testConstants.widgetNames.tierTwoTitle,
},
{
Name: packageNames.TIER_THREE,
Text: "",
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: testConstants.widgetNames.tierThreeTitle,
},
],
},
DefaultPackageItemDescriptions: {
Answers: [
{
Name: "Item1",
Text: testConstants.defaultItemCopy.itemOne,
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: "",
},
{
Name: "Item2",
Text: testConstants.defaultItemCopy.itemTwo,
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: "",
},
{
Name: "Item3",
Text: testConstants.defaultItemCopy.itemThree,
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: "",
},
],
},
VapsItemDescriptions: {
Answers: [
{
Name: partTypeStrings.FRONT_WIPER,
Text: testConstants.vapsCopy.frontWiperCopy,
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: "",
},
{
Name: partTypeStrings.REAR_WIPER,
Text: testConstants.vapsCopy.rearWiperCopy,
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: "",
},
{
Name: partTypeStrings.RAIN_DEFENSE,
Text: testConstants.vapsCopy.rainDefenseCopy,
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: "",
},
],
},
};
});
describe("General functionality", () => {
it('Should properly "Round Down" package tier', async () => {
// Slightly longer explanation:
// Should only return the highest tier where *every* offered VAP is part of the order.
// However, there may be vaps not offered in the qualifying tier. Hence rounding *down*.
//
// I.e. Economy=[], Standard=[front wipers], Premium=[front wipers, rain defense].
// Current vaps=[rain defense]. Though rain defense is in Premium, we don't satisfy it or standard.
// So our tier should still be Economy.
// Should still display extra vaps.
// Arrange
let props = generateDefaultProps();
props.lineItems.vaps = [testConstants.parts.rainDefensePart];
const { wrapper } = setupMocks({
propsData: props,
});
// Act
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.packageNameWidget).toEqual(testConstants.widgetNames.tierOneTitle);
let containsRainDefenseCopy = wrapper.vm.displayContent.includes(
testConstants.vapsCopy.rainDefenseCopy
);
expect(containsRainDefenseCopy).toBe(true);
});
it("Should display all default items from cms", async () => {
// Arrange
cmsContent.DefaultPackageItemDescriptions.Answers.push({
Name: "Item4",
Text: testConstants.defaultItemCopy.itemFour,
SubText: "",
ImageId: testConstants.imageId,
Image: "",
SubWidgetName: "",
});
let props = generateDefaultProps();
props.lineItems.vaps = [];
const { wrapper } = setupMocks({
propsData: props,
});
// Act
await wrapper.vm.$nextTick();
// Assert
let expectedResult = [
testConstants.defaultItemCopy.itemOne,
testConstants.defaultItemCopy.itemTwo,
testConstants.defaultItemCopy.itemThree,
testConstants.defaultItemCopy.itemFour,
];
expect(wrapper.vm.displayContent).toEqual(expectedResult);
});
it("Should display vaps if and only if they are added", async () => {
// Arrange
const { wrapper } = setupMocks({
propsData: generateDefaultProps(),
});
// Act
await wrapper.vm.$nextTick();
// Assert
const includesFrontWiperCopy = wrapper.vm.displayContent.includes(
testConstants.vapsCopy.frontWiperCopy
);
const includesRainDefenseCopy = wrapper.vm.displayContent.includes(
testConstants.vapsCopy.rainDefenseCopy
);
expect(includesFrontWiperCopy).toBe(true);
expect(includesRainDefenseCopy).toBe(false);
});
it("Should not error if cms content is missing (though may display poorly).", async () => {
// Arrange
cmsContent = {};
const { wrapper } = setupMocks({
propsData: generateDefaultProps(),
});
// Act
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.packageNameWidget).toEqual("");
expect(wrapper.vm.displayContent).toEqual([]);
});
});
describe("Match Figma Scenarios", () => {
figmaScenarios.forEach((scenario) => {
scenario.iterations.forEach((iteration) => {
it(`Should match figma scenario "${scenario.name}", iteration "${iteration.name}"`, async () => {
// Arrange
let props = generateDefaultProps();
props.availableVaps = scenario.params.availableVaps;
props.damage = scenario.params.damage;
props.glassParts = scenario.params.glassParts;
props.lineItems.supportingItems = scenario.params.supportingItems;
props.lineItems.vaps = iteration.vapsCombo;
const { wrapper } = setupMocks({
propsData: props,
});
// Act
await wrapper.vm.$nextTick();
// Assert
expect(wrapper.vm.packageNameWidget).toEqual(
iteration.expected.packageNameWidget
);
expect(wrapper.vm.displayContent).toEqual(iteration.expected.displayContent);
});
});
});
});
});
function generateDefaultProps() {
return {
servicePackageOptionsCmsName: testConstants.cmsPropValues.servicePackageOptionsCmsName,
defaultPackageItemsCmsName: testConstants.cmsPropValues.defaultPackageItemsCmsName,
vapsItemsCmsName: testConstants.cmsPropValues.vapsItemsCmsName,
availableVaps: [testConstants.parts.frontWiperPart, testConstants.parts.rainDefensePart],
lineItems: {
glassParts: [],
supportingItems: [],
vaps: [testConstants.parts.frontWiperPart],
},
damage: {
isRepair: false,
glassToReplace: [testConstants.damages.frontWindshield],
},
};
}
function setupMocks(customMountOptions) {
const mountOptions = getMountOptions(customMountOptions);
const mockMixin = {
methods: {
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
}),
},
};
mountOptions.global.mixins = [mockMixin];
const wrapper = shallowMount(servicePackageReview, mountOptions);
wrapper.vm.setCmsContent = jest.fn();
return { wrapper };
}

View file

@ -0,0 +1,104 @@
<template>
<reviewBlock
:headerCmsWidgetName="packageNameWidget"
:content="displayContent"
@edit-clicked="editClicked" />
</template>
<script>
import reviewBlock from "@/layouts/review/review-block/review-block";
import {
getHighestFullySatisfiedTier,
containsLineItemWithPartType,
} from "@/helpers/service-package-helper";
export default {
name: "service-package-review",
props: {
servicePackageOptionsCmsName: String,
defaultPackageItemsCmsName: String,
vapsItemsCmsName: String,
availableVaps: Array,
lineItems: Object,
damage: Object,
},
data() {
return {};
},
methods: {
editClicked() {
this.$emit("edit-clicked");
},
},
computed: {
displayContent() {
return [...this.defaultPackageText, ...this.vapsItemText];
},
packageNameWidget() {
const servicePackageNames = this.getCmsContent(
this.servicePackageOptionsCmsName,
"Answers"
);
if (!servicePackageNames) {
return "";
}
const currentPackage = servicePackageNames.find(
(entry) => entry.Name === this.packageLevel
);
return currentPackage.SubWidgetName;
},
defaultPackageText() {
const defaultItems = this.getCmsContent(this.defaultPackageItemsCmsName, "Answers");
if (!defaultItems) {
return [];
}
return defaultItems.map((answer) => answer.Text);
},
vapsItemText() {
const vapsDescriptions = this.getCmsContent(this.vapsItemsCmsName, "Answers");
if (!vapsDescriptions) {
return [];
}
const vapsDescriptionsOnOrder = vapsDescriptions.filter((answer) =>
containsLineItemWithPartType(answer.Name, this.vaps)
);
return vapsDescriptionsOnOrder.map((answer) => answer.Text);
},
packageLevel() {
return getHighestFullySatisfiedTier(
this.glassToReplace,
this.availableLineItems,
this.isRepair,
this.vaps
);
},
glassToReplace() {
return this.damage.glassToReplace;
},
isRepair() {
return this.damage.isRepair;
},
vaps() {
return this.lineItems?.vaps;
},
availableLineItems() {
return [
...(this.lineItems?.glassParts ?? []),
...(this.lineItems?.supportingItems ?? []),
...this.availableVaps,
];
},
},
components: {
reviewBlock,
},
};
</script>

View file

@ -27,7 +27,9 @@
class="mb-2"
@click-event="forwardButtonAction" />
<hr />
<div>
<hr />
</div>
<textBlock
customText="Appointment Details"
@ -48,9 +50,22 @@
cmsWidgetName="DamageReviewWidget"
:damage="damageInfo"
@edit-clicked="editDamage" />
<hr class="my-0" />
<servicePackageReview
servicePackageOptionsCmsName="ServicePackageTitle"
defaultPackageItemsCmsName="DefaultPackageItemDescriptions"
vapsItemsCmsName="VapsItemDescriptions"
:damage="damageInfo"
:availableVaps="availableVaps"
:lineItems="lineItems"
@edit-clicked="editServicePackage" />
</div>
<hr class="my-0" />
<div>
<hr class="my-0" />
</div>
<funnelFooter
cmsWidgetName="FunnelFooterWidget"
@ -66,17 +81,26 @@ import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
import vehicleBanner from "@/fmg-components/vehicle-banner/vehicle-banner";
import buttonMain from "@/ux-components/button-main/button-main";
import textBlock from "@/digital-components/text-block/text-block";
import vehicleReview from "@/layouts/review/review-sections/vehicle-review/vehicle-review";
import damageReview from "@/layouts/review/review-sections/damage-review/damage-review";
import servicePackageReview from "@/layouts/review/review-sections/service-package-review/service-package-review";
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
import { settleAllPromises } from "@/helpers/layout-helper";
import baseMixin from "@/mixins/base-mixin.js";
import { storeActions } from "@/constants/store-actions";
export default {
name: "review",
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
// Get rain defense and wiper availability for package review section.
const wipersPromise = baseMixin.methods.dispatchStoreAction(storeActions.GET_WIPERS);
const rainDefensePromise = baseMixin.methods.dispatchStoreAction(
storeActions.GET_RAIN_DEFENSE
);
// Settle promises and get results
const promiseResultMap = [
@ -84,16 +108,30 @@ export default {
resultKey: "cmsContent",
promise: cmsContentPromise,
},
{
resultKey: "wipers",
promise: wipersPromise,
},
{
resultKey: "rainDefense",
promise: rainDefensePromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
vm.availableWipers = resultMap.wipers;
vm.availableRainDefense = [resultMap.rainDefense];
});
},
data() {
return {};
return {
availableWipers: null,
availableRainDefense: null,
};
},
methods: {
arePagePrerequisitesValid() {
@ -113,6 +151,12 @@ export default {
this.$route
);
},
editServicePackage() {
this.$router.navigateWithoutSaving(
this.navigationScenarios.CLICKED_SERVICE_PACKAGE_EDIT,
this.$route
);
},
},
computed: {
subHeaderTitle() {
@ -130,6 +174,12 @@ export default {
damageInfo() {
return this.$store.getters.damage;
},
availableVaps() {
return [...(this.availableWipers ?? []), ...(this.availableRainDefense ?? [])];
},
lineItems() {
return this.$store.getters.lineItems;
},
},
components: {
funnelHeader,
@ -139,6 +189,7 @@ export default {
textBlock,
vehicleReview,
damageReview,
servicePackageReview,
},
};
</script>

View file

@ -49,6 +49,7 @@ const navigationScenarios = {
// Review
CLICKED_VEHICLE_EDIT: "CLICKED_VEHICLE_EDIT",
CLICKED_DAMAGE_EDIT: "CLICKED_DAMAGE_EDIT",
CLICKED_SERVICE_PACKAGE_EDIT: "CLICKED_SERVICE_PACKAGE_EDIT",
};
export { navigationScenarios };

View file

@ -472,6 +472,10 @@ const routingTable = function (store) {
scenario: navigationScenarios.CLICKED_DAMAGE_EDIT,
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
},
{
scenario: navigationScenarios.CLICKED_SERVICE_PACKAGE_EDIT,
destinationFmgPageValue: fmgPageValues.QUOTE,
},
{
scenario: navigationScenarios.CLICKED_BACK,
destinationFmgPageValue: fmgPageValues.CUSTOMER_DETAILS,

View file

@ -13,6 +13,7 @@ import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js";
import { deepEqual } from "@/helpers/object-helper";
import { AppointmentTypeStrings, PREMIUM_FEE_PART_TYPE } from "@/constants/schedule-constants";
import { partTypeStrings } from "@/constants/part-type-strings";
// Export State
const getDefaultState = () => {
@ -536,6 +537,14 @@ export const getters = {
isMobileAppointment: (state) => {
return state.order.serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
},
isRecalibrationOnOrder: (state) => {
return getHasRecalibrationPart(state);
},
areRearWipersOnOrder: (state) => {
return !!state.order.lineItems.vaps?.some(
(vap) => vap.partType.toUpperCase() === partTypeStrings.REAR_WIPER.toUpperCase()
);
},
lineItems: (state) => state.order.lineItems,
pageData: (state) => (page) => {
return state.applicationUser.pageData[page];