Merge pull request #323 from Safelite/feature/digital/SSR-476
Feature/digital/ssr 476
This commit is contained in:
commit
9dcc53c612
4 changed files with 120 additions and 64 deletions
|
|
@ -0,0 +1,41 @@
|
||||||
|
export const allGlassPartsAndItemsHavePrices = (lineItems) => {
|
||||||
|
if (lineItems.glassParts && Array.isArray(lineItems.glassParts)) {
|
||||||
|
if(!processLineItems(lineItems.glassParts))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lineItems.supportingItems && Array.isArray(lineItems.supportingItems)) {
|
||||||
|
if(!processLineItems(lineItems.supportingItems))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lineItems.vaps && Array.isArray(lineItems.vaps)) {
|
||||||
|
if(!processLineItems(lineItems.vaps))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const processLineItems = (lineItems) => {
|
||||||
|
let returnVal = true;
|
||||||
|
lineItems.forEach( lineItem => {
|
||||||
|
if (!hasPrice(lineItem)) {
|
||||||
|
returnVal = false;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return returnVal;
|
||||||
|
}
|
||||||
|
|
||||||
|
const hasPrice = (lineItem) => {
|
||||||
|
const value = (!!lineItem?.kitPrice && lineItem.kitPrice != 0) ||
|
||||||
|
(!!lineItem?.laborAmount && lineItem.laborAmount != 0) ||
|
||||||
|
(!!lineItem?.sellingPrice && lineItem.sellingPrice != 0);
|
||||||
|
return value;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { allGlassPartsAndItemsHavePrices } from './service-package-helper';
|
||||||
|
|
||||||
|
it("service package helper should return false when line item has missing price", () => {
|
||||||
|
// Arrange
|
||||||
|
const mockData = { glassParts: [{partNumber: 'DW01571GBNNOEE', sellingPrice: 25}], supportingItems: [{ laborAmount: 0 }] }
|
||||||
|
// Act
|
||||||
|
const actual = allGlassPartsAndItemsHavePrices(mockData);
|
||||||
|
// Assert
|
||||||
|
expect(actual).toEqual(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("service package helper should return true when line item has all prices", () => {
|
||||||
|
// Arrange
|
||||||
|
const mockData = { glassParts: [{partNumber: 'DW01571GBNNOEE', sellingPrice: 25}], laborAmount: [{ sellingPrice: 10 }] }
|
||||||
|
// Act
|
||||||
|
const actual = allGlassPartsAndItemsHavePrices(mockData);
|
||||||
|
// Assert
|
||||||
|
expect(actual).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
@ -13,9 +13,10 @@
|
||||||
import buttonQuestion from '@/digital-components/button-question/button-question';
|
import buttonQuestion from '@/digital-components/button-question/button-question';
|
||||||
import { processIfStatements } from '@/helpers/cms-content-helper';
|
import { processIfStatements } from '@/helpers/cms-content-helper';
|
||||||
import { damageLocationsSelected as glassLocations } from '@/constants/damage-locations-selected';
|
import { damageLocationsSelected as glassLocations } from '@/constants/damage-locations-selected';
|
||||||
import servicePackageRadio from './service-package-radio/service-package-radio';
|
import servicePackageRadio from '@/layouts/service-packages/service-package-question/service-package-radio/service-package-radio';
|
||||||
import { partTypeStrings } from '@/constants/part-type-strings';
|
import { partTypeStrings } from '@/constants/part-type-strings';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
|
import { allGlassPartsAndItemsHavePrices } from '@/layouts/service-packages/service-package-helper/service-package-helper'
|
||||||
|
|
||||||
const packageNames = {
|
const packageNames = {
|
||||||
TIER_ONE: 'TierOne',
|
TIER_ONE: 'TierOne',
|
||||||
|
|
@ -43,7 +44,7 @@
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
availableLineItems() {
|
availableLineItems() {
|
||||||
if (this.allGlassPartsAndItemsHavePrices(store.order.lineItems)) {
|
if (allGlassPartsAndItemsHavePrices(store.order.lineItems)) {
|
||||||
this.selectDefaultPackage();
|
this.selectDefaultPackage();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -170,7 +171,7 @@
|
||||||
},
|
},
|
||||||
getPackagePriceString(packageName) {
|
getPackagePriceString(packageName) {
|
||||||
const formattedPriceFloat = parseFloat(this.getPackagePrice(packageName)).toFixed(2);
|
const formattedPriceFloat = parseFloat(this.getPackagePrice(packageName)).toFixed(2);
|
||||||
return '$' + formattedPriceFloat;
|
return '$' + formattedPriceFloat + '*';
|
||||||
},
|
},
|
||||||
getPackagePrice(packageName) {
|
getPackagePrice(packageName) {
|
||||||
let priceFloat = 0;
|
let priceFloat = 0;
|
||||||
|
|
@ -312,37 +313,6 @@
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
allGlassPartsAndItemsHavePrices() {
|
|
||||||
if (this.pricedGlassParts) {
|
|
||||||
for (let i = 0; i < this.pricedGlassParts.length; i++) {
|
|
||||||
if (this.priceIsNullOrZero(this.pricedGlassParts[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.supportingItems) {
|
|
||||||
for (let i = 0; i < this.supportingItems.length; i++) {
|
|
||||||
if (this.priceIsNullOrZero(this.supportingItems[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.selectedVaps) {
|
|
||||||
for (let i = 0; i < this.selectedVaps.length; i++) {
|
|
||||||
if (this.priceIsNullOrZero(this.selectedVaps[i])) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
priceIsNullOrZero(lineItem) {
|
|
||||||
return (
|
|
||||||
(lineItem.kitPrice == null || lineItem.kitPrice == 0) &&
|
|
||||||
(lineItem.laborAmount == null || lineItem.laborAmount == 0) &&
|
|
||||||
(lineItem.sellingPrice == null || lineItem.sellingPrice == 0)
|
|
||||||
);
|
|
||||||
},
|
|
||||||
getLineItemsContainingPartType(partType) {
|
getLineItemsContainingPartType(partType) {
|
||||||
const partTypeMatches = this.nullSafeAvailableLineItems.filter(
|
const partTypeMatches = this.nullSafeAvailableLineItems.filter(
|
||||||
(lineItem) => lineItem.partType.toUpperCase() === partType
|
(lineItem) => lineItem.partType.toUpperCase() === partType
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,40 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="page-container-grouped-styles">
|
<div class="page-container-grouped-styles">
|
||||||
<loadingModal ref="loadingModal" />
|
|
||||||
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
|
||||||
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget"
|
|
||||||
justification="left"
|
|
||||||
issContainingPage="service-packages"
|
|
||||||
class="my-5"/>
|
|
||||||
<div class="fade-on-route-transition sub-container make-tall">
|
<div class="fade-on-route-transition sub-container make-tall">
|
||||||
<servicePackageQuestion ref="servicePackage"
|
<siteHeader cmsWidgetName="SiteHeaderWidget" />
|
||||||
cmsWidgetName="ServicePackage"
|
<siteSubHeader cmsWidgetName="SiteSubHeaderWidget"
|
||||||
groupName="ServicePackageQuestion"
|
justification="left"
|
||||||
:availableLineItems="availableLineItems"
|
issContainingPage="service-packages"
|
||||||
@vapsItemsSelected="vapsItemsSelectedAction"
|
/>
|
||||||
v-on:link-event="openModalAction"
|
<div class="mx-5">
|
||||||
validationRules="option-required"
|
|
||||||
isRequired />
|
<servicePackageQuestion ref="servicePackage"
|
||||||
<textBlock cmsWidgetName="PriceDisclaimerWidget"
|
cmsWidgetName="ServicePackage"
|
||||||
justifyText="left"
|
groupName="ServicePackageQuestion"
|
||||||
typeStyle="caption"
|
:availableLineItems="availableLineItems"
|
||||||
style="margin-bottom: 6rem;"
|
@vapsItemsSelected="vapsItemsSelectedAction"
|
||||||
class="mt-2 mx-6" />
|
v-on:link-event="openModalAction"
|
||||||
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
validationRules="option-required"
|
||||||
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
isRequired
|
||||||
<contentGroupModal ref="RearWiperModal" cmsWidgetName="RearWiperModal" />
|
/>
|
||||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
|
||||||
<siteFooter cmsWidgetName="SiteFooterWidget"
|
<p class="caption disclaimer" v-html="PriceDisclaimerText"></p>
|
||||||
:isForwardActionDisabled="!meta.valid"
|
|
||||||
@back-clicked="backButtonAction"
|
<siteFooter cmsWidgetName="SiteFooterWidget"
|
||||||
@ForwardClicked="forwardButtonAction" />
|
:isForwardActionDisabled="!meta.valid"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<loadingModal ref="loadingModal" />
|
||||||
|
<contentGroupModal ref="RainDefenseModal" cmsWidgetName="RainDefenseModal" />
|
||||||
|
<contentGroupModal ref="FrontWiperModal" cmsWidgetName="FrontWiperModal" />
|
||||||
|
<contentGroupModal ref="RearWiperModal" cmsWidgetName="RearWiperModal" />
|
||||||
|
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||||
|
|
||||||
|
|
||||||
</Form>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -50,6 +54,7 @@
|
||||||
import { required } from '@/helpers/validation-rules';
|
import { required } from '@/helpers/validation-rules';
|
||||||
import { errorMessages } from '@/constants/error-messages';
|
import { errorMessages } from '@/constants/error-messages';
|
||||||
import { Form, defineRule } from 'vee-validate';
|
import { Form, defineRule } from 'vee-validate';
|
||||||
|
import { allGlassPartsAndItemsHavePrices } from '@/layouts/service-packages/service-package-helper/service-package-helper'
|
||||||
|
|
||||||
defineRule('option-required', required(errorMessages.OPTION_REQUIRED));
|
defineRule('option-required', required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
|
|
@ -113,6 +118,11 @@
|
||||||
pricedGlassParts: []
|
pricedGlassParts: []
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
PriceDisclaimerText() {
|
||||||
|
return this.getCmsContent("PriceDisclaimerWidget", "Text");
|
||||||
|
},
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openModalAction(modalName) {
|
openModalAction(modalName) {
|
||||||
this.$refs[modalName.args].openModal();
|
this.$refs[modalName.args].openModal();
|
||||||
|
|
@ -134,7 +144,8 @@
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
forwardButtonAction() {
|
forwardButtonAction() {
|
||||||
if (!this.$ref.servicePackage.allGlassPartsAndItemsHavePrices()) {
|
const parts = { glassParts: this.pricedGlassParts, supportingItems: this.supportingItems, vaps: this.selectedVaps };
|
||||||
|
if (!allGlassPartsAndItemsHavePrices(parts)) {
|
||||||
console.error('One or more items have no price assigned!');
|
console.error('One or more items have no price assigned!');
|
||||||
}
|
}
|
||||||
if (this.pricedGlassParts.length > 0) {
|
if (this.pricedGlassParts.length > 0) {
|
||||||
|
|
@ -159,3 +170,18 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.subheader-secondary {
|
||||||
|
margin-top: .5rem;
|
||||||
|
padding: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disclaimer {
|
||||||
|
margin-top: 1.3rem;
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #4D5151;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
Loading…
Reference in a new issue