Merge pull request #587 from Safelite/feature/digital/SSR-1148
Adds Cart Footer
This commit is contained in:
commit
5604d089ea
5 changed files with 170 additions and 67 deletions
|
|
@ -5,5 +5,12 @@ Object {
|
||||||
"baseServiceLineItems": Array [],
|
"baseServiceLineItems": Array [],
|
||||||
"deductible": null,
|
"deductible": null,
|
||||||
"isExpanded": false,
|
"isExpanded": false,
|
||||||
|
"widget": Object {
|
||||||
|
"amountDue": "AmountDueTextWidget",
|
||||||
|
"basePrice": "BasePriceWidget",
|
||||||
|
"deductible": "DeductibleWidget",
|
||||||
|
"salesTax": "SalesTaxWidget",
|
||||||
|
"subtotal": "SubtotalWidget",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
|
||||||
|
|
@ -121,6 +121,58 @@ describe('cart-dropdown component', () => {
|
||||||
// Assert
|
// Assert
|
||||||
expect(cartBasePrice.exists()).toBeTruthy();
|
expect(cartBasePrice.exists()).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
test('cart footer', () => {
|
||||||
|
// Arrange
|
||||||
|
const reference = '#cart-footer';
|
||||||
|
const isExpanded = true;
|
||||||
|
const initialData = { isExpanded };
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, initialData);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const cartFooter = wrapper.find(reference);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(cartFooter.exists()).toBeTruthy();
|
||||||
|
});
|
||||||
|
test('subtotal', () => {
|
||||||
|
// Arrange
|
||||||
|
const reference = '#cart-subtotal';
|
||||||
|
const isExpanded = true;
|
||||||
|
const initialData = { isExpanded };
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, initialData);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const subtotal = wrapper.find(reference);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(subtotal.exists()).toBeTruthy();
|
||||||
|
});
|
||||||
|
test('tax', () => {
|
||||||
|
// Arrange
|
||||||
|
const reference = '#cart-sales-tax';
|
||||||
|
const isExpanded = true;
|
||||||
|
const initialData = { isExpanded };
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, initialData);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const salesTax = wrapper.find(reference);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(salesTax.exists()).toBeTruthy();
|
||||||
|
});
|
||||||
|
test('bottom amount due', () => {
|
||||||
|
// Arrange
|
||||||
|
const reference = '#bottom-amount-due';
|
||||||
|
const isExpanded = true;
|
||||||
|
const initialData = { isExpanded };
|
||||||
|
const { wrapper } = getMountedComponent({}, {}, initialData);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const bottomAmountDue = wrapper.find(reference);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(bottomAmountDue.exists()).toBeTruthy();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
describe('does not display', () => {
|
describe('does not display', () => {
|
||||||
test('cart deductible when showDeductibleLineItem is false', () => {
|
test('cart deductible when showDeductibleLineItem is false', () => {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<div :class="[isExpanded ? 'pb-3' : 'pb-4']">
|
<div :class="[isExpanded ? 'pb-5' : 'pb-4']">
|
||||||
<div
|
<div
|
||||||
id="cart-dropdown-head"
|
id="cart-dropdown-head"
|
||||||
class="row cart-toggle flex align-items-center pt-4"
|
class="row cart-toggle flex align-items-center pt-4"
|
||||||
|
|
@ -9,50 +9,73 @@
|
||||||
aria-label="expand cart details"
|
aria-label="expand cart details"
|
||||||
href="javascript:void(0)"
|
href="javascript:void(0)"
|
||||||
class="col d-flex justify-content-between py-0">
|
class="col d-flex justify-content-between py-0">
|
||||||
<span class="cart-label color-black">{{ amountDueLabel }}</span>
|
<span class="color-black">{{ amountDueLabel }}</span>
|
||||||
<span class="cart-label amount-due">{{ getDisplayed(amountDue) }}</span>
|
<span class="color-green">{{ getDisplayed(amountDue) }}</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
id="cart-table"
|
id="cart-table"
|
||||||
class="cart-table">
|
class="cart-table">
|
||||||
<!-- Deductible Line Item -->
|
|
||||||
<div
|
<div
|
||||||
id="cart-deductible-or-base-price"
|
id="cart-line-items"
|
||||||
class="mt-4 cart-line-item color-gray-100 px-5 py-1">
|
class="color-darker-gray">
|
||||||
<div
|
<div
|
||||||
v-if="showDeductibleLineItem"
|
id="cart-deductible-or-base-price"
|
||||||
id="cart-deductible"
|
class="cart-deductible-or-base-price">
|
||||||
class="d-flex justify-content-between align-items-center">
|
<div
|
||||||
<span
|
v-if="showDeductibleLineItem"
|
||||||
id="deductible-label"
|
id="cart-deductible"
|
||||||
class="cart-label">{{ deductibleLabel }}</span>
|
class="d-flex justify-content-between align-items-center">
|
||||||
<span id="deductible-value">{{ getDisplayed(deductible) }}</span>
|
<span id="deductible-label">{{ deductibleLabel }}</span>
|
||||||
|
<span id="deductible-value">{{ getDisplayed(deductible) }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else
|
||||||
|
id="cart-base-price"
|
||||||
|
class="d-flex justify-content-between align-items-center">
|
||||||
|
<span id="base-price-label">{{ basePriceLabel }}</span>
|
||||||
|
<span id="base-price-value">{{ getDisplayed(baseServicePrice) }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
v-else
|
<!-- Packaged Cart Items -->
|
||||||
id="cart-base-price"
|
|
||||||
class="d-flex justify-content-between align-items-center">
|
<!-- Nonpackaged Cart Items -->
|
||||||
<span
|
<!-- This will be a loop when this is implemented -->
|
||||||
id="base-price-label"
|
<div class="non-packaged-cart-item">
|
||||||
class="cart-label">{{ basePriceLabel }}</span>
|
<textLink
|
||||||
<span id="base-price-value">{{ getDisplayed(baseServicePrice) }}</span>
|
linkType="text"
|
||||||
|
text="Recycling"
|
||||||
|
href="javascript:void(0)"
|
||||||
|
@clickEvent="openModal(recyclingModalCmsWidgetName)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
<!-- Packaged Cart Items -->
|
id="cart-footer"
|
||||||
|
class="cart-footer">
|
||||||
<!-- Nonpackaged Cart Items -->
|
<div
|
||||||
<!-- This will be a loop when this is implemented -->
|
id="cart-subtotal-and-tax"
|
||||||
<div class="non-packaged-cart-item">
|
class="subtotal-and-tax">
|
||||||
<textLink
|
<div
|
||||||
linkType="text"
|
id="cart-subtotal"
|
||||||
text="Recycling"
|
class="col d-flex justify-content-between">
|
||||||
href="javascript:void(0)"
|
<span id="subtotal-label">{{ subtotalLabel }}</span>
|
||||||
@clickEvent="openModal(recyclingModalCmsWidgetName)" />
|
<span id="subtotal-value">{{ getDisplayed(subTotal) }}</span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="cart-sales-tax"
|
||||||
|
class="pt-1 col d-flex justify-content-between">
|
||||||
|
<span id="sales-tax-label">{{ salesTaxLabel }}</span>
|
||||||
|
<span id="sales-tax-value">{{ getDisplayed(salesTax) }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
id="bottom-amount-due"
|
||||||
|
class="bottom-amount-due col d-flex justify-content-between">
|
||||||
|
<span id="bottom-amount-due-label">{{ amountDueLabel }}</span>
|
||||||
|
<span id="bottom-amount-due-value">{{ getDisplayed(amountDue) }}</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Sub total, sales tax, total columns -->
|
|
||||||
</div>
|
</div>
|
||||||
<contentGroupModal
|
<contentGroupModal
|
||||||
ref="RecycleModal"
|
ref="RecycleModal"
|
||||||
|
|
@ -69,6 +92,7 @@ import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||||
import getPriceOfLineItems from '@/helpers/price-calculator.js';
|
import getPriceOfLineItems from '@/helpers/price-calculator.js';
|
||||||
import { formatAmountInDollars } from '@/helpers/text-helper.js';
|
import { formatAmountInDollars } from '@/helpers/text-helper.js';
|
||||||
|
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||||
|
|
||||||
const VERIFYING_COVERAGE = 'Verifying coverage';
|
const VERIFYING_COVERAGE = 'Verifying coverage';
|
||||||
|
|
||||||
|
|
@ -78,9 +102,6 @@ export default {
|
||||||
textBlock,
|
textBlock,
|
||||||
textLink },
|
textLink },
|
||||||
props: {
|
props: {
|
||||||
amountDueLabel: String,
|
|
||||||
basePriceLabel: String,
|
|
||||||
deductibleLabel: String,
|
|
||||||
recyclingModalCmsWidgetName: String,
|
recyclingModalCmsWidgetName: String,
|
||||||
showAsPaid: Boolean
|
showAsPaid: Boolean
|
||||||
},
|
},
|
||||||
|
|
@ -95,7 +116,14 @@ export default {
|
||||||
return {
|
return {
|
||||||
deductible: currentDeductible,
|
deductible: currentDeductible,
|
||||||
baseServiceLineItems,
|
baseServiceLineItems,
|
||||||
isExpanded: false
|
isExpanded: false,
|
||||||
|
widget: {
|
||||||
|
amountDue: 'AmountDueTextWidget',
|
||||||
|
deductible: 'DeductibleWidget',
|
||||||
|
basePrice: 'BasePriceWidget',
|
||||||
|
subtotal: 'SubtotalWidget',
|
||||||
|
salesTax: 'SalesTaxWidget'
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -120,6 +148,21 @@ export default {
|
||||||
return this.showAsPaid
|
return this.showAsPaid
|
||||||
? 0
|
? 0
|
||||||
: this.subTotal + this.salesTax;
|
: this.subTotal + this.salesTax;
|
||||||
|
},
|
||||||
|
amountDueLabel() {
|
||||||
|
return this.getCmsContent(this.widget.amountDue, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||||
|
},
|
||||||
|
deductibleLabel() {
|
||||||
|
return this.getCmsContent(this.widget.deductible, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||||
|
},
|
||||||
|
basePriceLabel() {
|
||||||
|
return this.getCmsContent(this.widget.basePrice, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||||
|
},
|
||||||
|
subtotalLabel() {
|
||||||
|
return this.getCmsContent(this.widget.subtotal, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||||
|
},
|
||||||
|
salesTaxLabel() {
|
||||||
|
return this.getCmsContent(this.widget.salesTax, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -136,7 +179,6 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
@ -145,11 +187,12 @@ export default {
|
||||||
.color-black {
|
.color-black {
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
.color-gray-100 {
|
|
||||||
background-color: $gray-100;
|
.color-green {
|
||||||
|
color: $green;
|
||||||
}
|
}
|
||||||
|
|
||||||
.cart-line-item {
|
.color-darker-gray {
|
||||||
color: $darker-gray;
|
color: $darker-gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -158,6 +201,29 @@ export default {
|
||||||
transition: all 350ms ease-in;
|
transition: all 350ms ease-in;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
|
||||||
|
.cart-deductible-or-base-price {
|
||||||
|
background-color: $gray-100;
|
||||||
|
margin-top: 1rem;
|
||||||
|
padding: 0.25rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cart-footer {
|
||||||
|
border-top: 1px solid $green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.subtotal-and-tax {
|
||||||
|
background-color: $green-150;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: $black;
|
||||||
|
padding: 0.25rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bottom-amount-due {
|
||||||
|
color: $white;
|
||||||
|
background-color: $green;
|
||||||
|
padding: 0.25rem 1.5rem;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
:deep(.modal-content a.external-text) {
|
:deep(.modal-content a.external-text) {
|
||||||
|
|
@ -175,6 +241,8 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.cart-toggle {
|
.cart-toggle {
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: "";
|
content: "";
|
||||||
transition: all 0.5s ease;
|
transition: all 0.5s ease;
|
||||||
|
|
@ -201,13 +269,6 @@ export default {
|
||||||
a {
|
a {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
.cart-label {
|
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
line-height: 1.625;
|
|
||||||
}
|
|
||||||
.amount-due {
|
|
||||||
color: $green;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -21,9 +21,6 @@
|
||||||
<hr class="my-0" />
|
<hr class="my-0" />
|
||||||
<cartDropdown
|
<cartDropdown
|
||||||
:showAsPaid="false"
|
:showAsPaid="false"
|
||||||
:amountDueLabel="amountDueText"
|
|
||||||
:deductibleLabel="deductibleLabel"
|
|
||||||
:basePriceLabel="basePriceLabel"
|
|
||||||
recyclingModalCmsWidgetName="RecycleModal" />
|
recyclingModalCmsWidgetName="RecycleModal" />
|
||||||
<hr class="mt-0 mb-5" />
|
<hr class="mt-0 mb-5" />
|
||||||
<div>Pia Alert Placeholder</div>
|
<div>Pia Alert Placeholder</div>
|
||||||
|
|
@ -61,7 +58,6 @@ import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||||
import { paymentMethods } from '@/constants/payment-method-constants';
|
import { paymentMethods } from '@/constants/payment-method-constants';
|
||||||
import globalRules from '@/constants/global-rules';
|
import globalRules from '@/constants/global-rules';
|
||||||
import { Form } from 'vee-validate';
|
import { Form } from 'vee-validate';
|
||||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
|
||||||
|
|
||||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||||
|
|
||||||
|
|
@ -109,11 +105,6 @@ export default {
|
||||||
paymentMethodInternalModel: this.getPaymentMethodFromStore(),
|
paymentMethodInternalModel: this.getPaymentMethodFromStore(),
|
||||||
rules: {
|
rules: {
|
||||||
optionRequired: globalRules.OPTION_REQUIRED
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
},
|
|
||||||
widget: {
|
|
||||||
amountDue: 'AmountDueTextWidget',
|
|
||||||
deductible: 'DeductibleWidget',
|
|
||||||
basePrice: 'BasePriceWidget'
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
@ -132,15 +123,6 @@ export default {
|
||||||
},
|
},
|
||||||
paymentMethod() {
|
paymentMethod() {
|
||||||
return this.paymentMethodInternalModel;
|
return this.paymentMethodInternalModel;
|
||||||
},
|
|
||||||
amountDueText() {
|
|
||||||
return this.getCmsContent(this.widget.amountDue, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
|
||||||
},
|
|
||||||
deductibleLabel() {
|
|
||||||
return this.getCmsContent(this.widget.deductible, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
|
||||||
},
|
|
||||||
basePriceLabel() {
|
|
||||||
return this.getCmsContent(this.widget.basePrice, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ $red-900: #330300;
|
||||||
|
|
||||||
// Greens
|
// Greens
|
||||||
$green-100: #e3f2ea;
|
$green-100: #e3f2ea;
|
||||||
|
$green-150: #e6f2ec;
|
||||||
$green-200: #bcedd4;
|
$green-200: #bcedd4;
|
||||||
$green-300: #94d7b6;
|
$green-300: #94d7b6;
|
||||||
$green-400: #5abc8c; // Used in theme
|
$green-400: #5abc8c; // Used in theme
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue