Merge pull request #587 from Safelite/feature/digital/SSR-1148

Adds Cart Footer
This commit is contained in:
michaela-brydon-safelite 2024-03-15 01:05:19 -04:00 committed by GitHub
commit 5604d089ea
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 170 additions and 67 deletions

View file

@ -5,5 +5,12 @@ Object {
"baseServiceLineItems": Array [],
"deductible": null,
"isExpanded": false,
"widget": Object {
"amountDue": "AmountDueTextWidget",
"basePrice": "BasePriceWidget",
"deductible": "DeductibleWidget",
"salesTax": "SalesTaxWidget",
"subtotal": "SubtotalWidget",
},
}
`;

View file

@ -121,6 +121,58 @@ describe('cart-dropdown component', () => {
// Assert
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', () => {
test('cart deductible when showDeductibleLineItem is false', () => {

View file

@ -1,5 +1,5 @@
<template>
<div :class="[isExpanded ? 'pb-3' : 'pb-4']">
<div :class="[isExpanded ? 'pb-5' : 'pb-4']">
<div
id="cart-dropdown-head"
class="row cart-toggle flex align-items-center pt-4"
@ -9,50 +9,73 @@
aria-label="expand cart details"
href="javascript:void(0)"
class="col d-flex justify-content-between py-0">
<span class="cart-label color-black">{{ amountDueLabel }}</span>
<span class="cart-label amount-due">{{ getDisplayed(amountDue) }}</span>
<span class="color-black">{{ amountDueLabel }}</span>
<span class="color-green">{{ getDisplayed(amountDue) }}</span>
</a>
</div>
<div
id="cart-table"
class="cart-table">
<!-- Deductible Line Item -->
<div
id="cart-deductible-or-base-price"
class="mt-4 cart-line-item color-gray-100 px-5 py-1">
id="cart-line-items"
class="color-darker-gray">
<div
v-if="showDeductibleLineItem"
id="cart-deductible"
class="d-flex justify-content-between align-items-center">
<span
id="deductible-label"
class="cart-label">{{ deductibleLabel }}</span>
<span id="deductible-value">{{ getDisplayed(deductible) }}</span>
id="cart-deductible-or-base-price"
class="cart-deductible-or-base-price">
<div
v-if="showDeductibleLineItem"
id="cart-deductible"
class="d-flex justify-content-between align-items-center">
<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
v-else
id="cart-base-price"
class="d-flex justify-content-between align-items-center">
<span
id="base-price-label"
class="cart-label">{{ basePriceLabel }}</span>
<span id="base-price-value">{{ getDisplayed(baseServicePrice) }}</span>
<!-- Packaged Cart Items -->
<!-- Nonpackaged Cart Items -->
<!-- This will be a loop when this is implemented -->
<div class="non-packaged-cart-item">
<textLink
linkType="text"
text="Recycling"
href="javascript:void(0)"
@clickEvent="openModal(recyclingModalCmsWidgetName)" />
</div>
</div>
<!-- Packaged Cart Items -->
<!-- Nonpackaged Cart Items -->
<!-- This will be a loop when this is implemented -->
<div class="non-packaged-cart-item">
<textLink
linkType="text"
text="Recycling"
href="javascript:void(0)"
@clickEvent="openModal(recyclingModalCmsWidgetName)" />
<div
id="cart-footer"
class="cart-footer">
<div
id="cart-subtotal-and-tax"
class="subtotal-and-tax">
<div
id="cart-subtotal"
class="col d-flex justify-content-between">
<span id="subtotal-label">{{ subtotalLabel }}</span>
<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>
<!-- Sub total, sales tax, total columns -->
</div>
<contentGroupModal
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 getPriceOfLineItems from '@/helpers/price-calculator.js';
import { formatAmountInDollars } from '@/helpers/text-helper.js';
import widgetFields from '@/constants/cms-widget-fields.js';
const VERIFYING_COVERAGE = 'Verifying coverage';
@ -78,9 +102,6 @@ export default {
textBlock,
textLink },
props: {
amountDueLabel: String,
basePriceLabel: String,
deductibleLabel: String,
recyclingModalCmsWidgetName: String,
showAsPaid: Boolean
},
@ -95,7 +116,14 @@ export default {
return {
deductible: currentDeductible,
baseServiceLineItems,
isExpanded: false
isExpanded: false,
widget: {
amountDue: 'AmountDueTextWidget',
deductible: 'DeductibleWidget',
basePrice: 'BasePriceWidget',
subtotal: 'SubtotalWidget',
salesTax: 'SalesTaxWidget'
}
};
},
computed: {
@ -120,6 +148,21 @@ export default {
return this.showAsPaid
? 0
: 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: {
@ -136,7 +179,6 @@ export default {
}
}
};
</script>
<style lang="scss" scoped>
@ -145,11 +187,12 @@ export default {
.color-black {
color: $black;
}
.color-gray-100 {
background-color: $gray-100;
.color-green {
color: $green;
}
.cart-line-item {
.color-darker-gray {
color: $darker-gray;
}
@ -158,6 +201,29 @@ export default {
transition: all 350ms ease-in;
overflow: 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) {
@ -175,6 +241,8 @@ export default {
}
.cart-toggle {
font-weight: $font-weight-bold;
&:after {
content: "";
transition: all 0.5s ease;
@ -201,13 +269,6 @@ export default {
a {
text-decoration: none;
}
.cart-label {
font-weight: $font-weight-bold;
line-height: 1.625;
}
.amount-due {
color: $green;
}
}
</style>

View file

@ -21,9 +21,6 @@
<hr class="my-0" />
<cartDropdown
:showAsPaid="false"
:amountDueLabel="amountDueText"
:deductibleLabel="deductibleLabel"
:basePriceLabel="basePriceLabel"
recyclingModalCmsWidgetName="RecycleModal" />
<hr class="mt-0 mb-5" />
<div>Pia Alert Placeholder</div>
@ -61,7 +58,6 @@ import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import { paymentMethods } from '@/constants/payment-method-constants';
import globalRules from '@/constants/global-rules';
import { Form } from 'vee-validate';
import widgetFields from '@/constants/cms-widget-fields.js';
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
@ -109,11 +105,6 @@ export default {
paymentMethodInternalModel: this.getPaymentMethodFromStore(),
rules: {
optionRequired: globalRules.OPTION_REQUIRED
},
widget: {
amountDue: 'AmountDueTextWidget',
deductible: 'DeductibleWidget',
basePrice: 'BasePriceWidget'
}
};
},
@ -132,15 +123,6 @@ export default {
},
paymentMethod() {
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: {

View file

@ -28,6 +28,7 @@ $red-900: #330300;
// Greens
$green-100: #e3f2ea;
$green-150: #e6f2ec;
$green-200: #bcedd4;
$green-300: #94d7b6;
$green-400: #5abc8c; // Used in theme