INSR-7759: Some payment-method parity updates
- Payment method question button now matches Heritage - Recalibration is now its own line item - Some other general updates to structure and formatting of page
This commit is contained in:
parent
9bc40980d8
commit
c821fc7d83
8 changed files with 174 additions and 137 deletions
BIN
src/assets/img/icons/chevron-circle_review_dropdown.png
Normal file
BIN
src/assets/img/icons/chevron-circle_review_dropdown.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
|
|
@ -60,10 +60,11 @@ export const pageProgressMapper = {
|
|||
percent: 85
|
||||
},
|
||||
'payment-method': {
|
||||
percent: 90
|
||||
percent: 95
|
||||
},
|
||||
'payment-page': {
|
||||
percent: 95
|
||||
// No progress bar on this page
|
||||
percent: 0
|
||||
},
|
||||
'tpa-search': {
|
||||
percent: 80
|
||||
|
|
|
|||
|
|
@ -142,3 +142,18 @@ export function getSalesTax(order) {
|
|||
export function getCartTotal(order) {
|
||||
return Math.round((getSubtotal(order) + getSalesTax(order)) * 100) / 100;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total price of all recal child parts on the order
|
||||
* @param {object} order order object
|
||||
* @returns {number} total price of all recal child parts on the order
|
||||
*/
|
||||
export function getRecalibrationTotal(order) {
|
||||
const itemsWithRecalibration = getServiceLineItems(order)
|
||||
.filter((item) => item.requiresRecalibration);
|
||||
const recalibrationLineItems = itemsWithRecalibration.map((item) => {
|
||||
return item.childParts?.find((child) => child.partType === partTypeStrings.RECALIBRATION || child.partType === partTypeStrings.ADAS_RECALIBRATION) ?? {};
|
||||
});
|
||||
|
||||
return getPriceOfLineItems(recalibrationLineItems);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,20 +1,30 @@
|
|||
<template>
|
||||
<div class="cart-table">
|
||||
<div
|
||||
v-if="!isDeductibleOnly"
|
||||
class="cart-table">
|
||||
<div class="cart-item-list">
|
||||
<div
|
||||
id="cart-deductible-or-base-price"
|
||||
v-if="showDeductibleCartItem"
|
||||
class="cart-item">
|
||||
<div class="price-row">
|
||||
<template
|
||||
v-if="showDeductibleCartItem">
|
||||
<span id="deductible-label">{{ deductibleLabel }}</span>
|
||||
<span id="deductible-value">{{ getDisplayed(deductible) }}</span>
|
||||
</template>
|
||||
<template
|
||||
v-else>
|
||||
<span id="base-price-label">{{ basePriceLabel }}</span>
|
||||
<span id="base-price-value">{{ getDisplayed(servicePrice) }}</span>
|
||||
</template>
|
||||
<span id="deductible-label">{{ deductibleLabel }}</span>
|
||||
<span id="deductible-value">{{ getDisplayed(deductible) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="cart-item">
|
||||
<div class="price-row">
|
||||
<span id="base-price-label">{{ basePriceLabel }}</span>
|
||||
<span id="base-price-value">{{ getDisplayed(servicePrice) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="showRecalibrationCartItem"
|
||||
class="cart-item">
|
||||
<div class="price-row">
|
||||
<span id="recalibration-label">{{ recalibrationLabel }}</span>
|
||||
<span id="recalibration-value">{{ getDisplayed(recalibrationPrice) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -24,16 +34,7 @@
|
|||
:key="i"
|
||||
class="cart-item non-packaged">
|
||||
<div class="price-row">
|
||||
<span
|
||||
v-if="item.cartItemType === cartItemType.RECYCLE_FEE"
|
||||
id="recycle-fee-label">
|
||||
<textLink
|
||||
linkType="text"
|
||||
:text="item?.name ?? ''"
|
||||
href="javascript:void(0)"
|
||||
@clickEvent="openModal(RECYCLING_MODAL_REF_NAME)" />
|
||||
</span>
|
||||
<span v-else>{{ item?.name ?? '' }}</span>
|
||||
<span>{{ item?.name ?? '' }}</span>
|
||||
<span>{{ formatAmountInDollars(item?.subTotal ?? 0) }}</span>
|
||||
</div>
|
||||
<textLink
|
||||
|
|
@ -103,11 +104,10 @@
|
|||
<span id="bottom-amount-due-value">{{ getDisplayed(amountDue) }}</span>
|
||||
</div>
|
||||
</div>
|
||||
<contentGroupModal
|
||||
:ref="RECYCLING_MODAL_REF_NAME"
|
||||
:cmsWidgetName="recyclingModalCmsWidgetName">
|
||||
<textBlock cmsWidgetName="RecycleTextBlock" />
|
||||
</contentGroupModal>
|
||||
</div>
|
||||
<div v-else class="deductible-box">
|
||||
<span class="deductible-label">{{ deductibleLabel }}</span>
|
||||
<span class="deductible-value">{{ getDisplayed(deductible) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -128,6 +128,7 @@ import {
|
|||
getCartTotal,
|
||||
getDeductible,
|
||||
getLineItems, getMobileFeeLineItem,
|
||||
getRecalibrationTotal,
|
||||
getRecycleFeeLineItem, getSalesTax,
|
||||
getServiceLineItems, getSubtotal, isOrderITAC, isOrderNoComp,
|
||||
isOrderUnverified
|
||||
|
|
@ -136,7 +137,6 @@ import { getPriceOfLineItems, getTaxOfLineItems } from '@/helpers/price-calculat
|
|||
import { processIfStatements } from '@/helpers/cms-content-helper';
|
||||
|
||||
const VERIFYING_COVERAGE = 'Verifying coverage';
|
||||
const RECYCLING_MODAL_REF_NAME = 'RecycleModal';
|
||||
|
||||
export default {
|
||||
name: 'confirmation-cart',
|
||||
|
|
@ -148,7 +148,6 @@ export default {
|
|||
props: {
|
||||
readOnly: Boolean,
|
||||
showAsPaid: Boolean,
|
||||
recyclingModalCmsWidgetName: String,
|
||||
submittedOrder: Object
|
||||
},
|
||||
data() {
|
||||
|
|
@ -158,6 +157,7 @@ export default {
|
|||
amountPaid: 'AmountPaidTextWidget',
|
||||
deductible: 'DeductibleWidget',
|
||||
basePrice: 'BasePriceWidget',
|
||||
recalibration: 'RecalibrationWidget',
|
||||
subtotal: 'SubtotalWidget',
|
||||
salesTax: 'SalesTaxWidget',
|
||||
recycleFee: 'RecycleFeeWidget',
|
||||
|
|
@ -167,8 +167,7 @@ export default {
|
|||
warrantyText: 'WarrantyCartItemTextWidget',
|
||||
guaranteeText: 'GuaranteeCartItemTextWidget'
|
||||
},
|
||||
cartItemType,
|
||||
RECYCLING_MODAL_REF_NAME
|
||||
cartItemType
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -181,9 +180,18 @@ export default {
|
|||
deductible() {
|
||||
return getDeductible(this.cartOrder);
|
||||
},
|
||||
isDeductibleOnly() {
|
||||
return this.deductible > 0 && this.subTotal === this.deductible;
|
||||
},
|
||||
showDeductibleCartItem() {
|
||||
return this.isUnverified || (!this.isNoComp && !this.isITAC);
|
||||
},
|
||||
showRecalibrationCartItem() {
|
||||
return this.recalibrationPrice > 0;
|
||||
},
|
||||
recalibrationPrice() {
|
||||
return getRecalibrationTotal(this.cartOrder);
|
||||
},
|
||||
lineItems() {
|
||||
return getLineItems(this.cartOrder);
|
||||
},
|
||||
|
|
@ -191,7 +199,8 @@ export default {
|
|||
return getRecycleFeeLineItem(this.cartOrder);
|
||||
},
|
||||
servicePrice() {
|
||||
return getPriceOfLineItems(getServiceLineItems(this.cartOrder)) ?? 0;
|
||||
const price = getPriceOfLineItems(getServiceLineItems(this.cartOrder)) ?? 0;
|
||||
return price - this.recalibrationPrice;
|
||||
},
|
||||
isUnverified() {
|
||||
return isOrderUnverified(this.cartOrder);
|
||||
|
|
@ -327,6 +336,9 @@ export default {
|
|||
this.getCustomValueFromString
|
||||
);
|
||||
},
|
||||
recalibrationLabel() {
|
||||
return this.getCmsContent(this.widget.recalibration, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
},
|
||||
subtotalLabel() {
|
||||
return this.getCmsContent(this.widget.subtotal, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
},
|
||||
|
|
@ -452,8 +464,6 @@ export default {
|
|||
<style lang="scss" scoped>
|
||||
@import "@/styles/ux-variables-svg-strings.scss";
|
||||
|
||||
$RECYCLING_MODAL_REF_NAME: 'RecycleModal';
|
||||
|
||||
.cart-table {
|
||||
max-height: 50rem;
|
||||
transition: all 150ms ease-in;
|
||||
|
|
@ -507,23 +517,20 @@ $RECYCLING_MODAL_REF_NAME: 'RecycleModal';
|
|||
background-color: $green;
|
||||
padding: .5rem 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.modal-content a.external-text) {
|
||||
text-underline-offset: 0.25rem;
|
||||
line-height: 2;
|
||||
padding: 0 0 0.25rem 0;
|
||||
font-weight: 500;
|
||||
max-width: -webkit-fit-content;
|
||||
max-width: -moz-fit-content;
|
||||
max-width: fit-content;
|
||||
}
|
||||
|
||||
:deep(##{$RECYCLING_MODAL_REF_NAME} h5) {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
:deep(#recycle-fee-label a){
|
||||
line-height: initial;
|
||||
.deductible-box {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .25rem;
|
||||
}
|
||||
.deductible-label {
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
}
|
||||
.deductible-value {
|
||||
color: $green;
|
||||
font-weight: 500;
|
||||
font-size: 1.625rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -2,32 +2,30 @@
|
|||
<baseInputButton
|
||||
v-bind="$props"
|
||||
v-model="selectedValue"
|
||||
buttonWrapperClasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2">
|
||||
<div class="button-content list-button-content d-flex flex-row py-3 px-4">
|
||||
buttonWrapperClasses="list-group base-input-button list-button d-flex flex-column w-100 no-hover">
|
||||
<div class="button-content list-button-content d-flex flex-row">
|
||||
<div>
|
||||
<span
|
||||
v-for="token in tokens"
|
||||
:key="token">
|
||||
<span v-if="isInlineImageToken(token)">
|
||||
<img
|
||||
v-if="hasImage"
|
||||
:src="buttonImage"
|
||||
:alt="getInlineAltText(token)" />
|
||||
<span v-else> {{ getInlineAltText(token) }}</span>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ token }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<img
|
||||
v-if="shouldDisplaySideImage"
|
||||
:id="buttonImageId"
|
||||
class="ms-auto order-3"
|
||||
class="ms-auto"
|
||||
:src="buttonImage"
|
||||
:alt="altText" />
|
||||
<div class="order-2">
|
||||
<p class="m-0">
|
||||
<span
|
||||
v-for="token in tokens"
|
||||
:key="token">
|
||||
<span v-if="isInlineImageToken(token)">
|
||||
<img
|
||||
v-if="hasImage"
|
||||
:src="buttonImage"
|
||||
:alt="getInlineAltText(token)" />
|
||||
<span v-else> {{ getInlineAltText(token) }}</span>
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ token }}
|
||||
</span>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</baseInputButton>
|
||||
</template>
|
||||
|
|
@ -78,48 +76,26 @@ export default {
|
|||
outline: none;
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
position: static; //override bootstrap
|
||||
|
||||
&:focus-visible + .list-button-content {
|
||||
box-shadow: 0 0 0 2.5px $blue;
|
||||
}
|
||||
&:focus + .list-button-content {
|
||||
box-shadow: 0 0 0 2.5px $blue;
|
||||
}
|
||||
&:checked + .list-button-content {
|
||||
background: $background-color-selected;
|
||||
border-color: $heritage-blue-primary;
|
||||
font-weight: 600;
|
||||
color: $black;
|
||||
font-weight: 500;
|
||||
background: $blue-100;
|
||||
box-shadow: 0 0 0 1px $blue;
|
||||
}
|
||||
&:checked:focus + .list-button-content {
|
||||
box-shadow: 0 0 0 2.5px $blue;
|
||||
}
|
||||
&:checked + .list-button-content p,
|
||||
&:checked + .list-button-content span {
|
||||
font-weight: 500;
|
||||
}
|
||||
&:checked + .list-button-content span:nth-child(2) {
|
||||
font-weight: 400;
|
||||
color: $gray-600;
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-button-content {
|
||||
color: $gray-600;
|
||||
color: $darker-gray;
|
||||
font-weight: 400;
|
||||
position: relative;
|
||||
background: $white;
|
||||
transition: all 150ms linear;
|
||||
border-radius: $border-radius-lg;
|
||||
border: 1px solid $gray-500;
|
||||
border-radius: 3.75rem;
|
||||
border: 1px solid #CACBCC;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
|
||||
span {
|
||||
&.small {
|
||||
font-size: $font-size-xsm;
|
||||
color: $gray-550;
|
||||
}
|
||||
}
|
||||
padding: .625rem 2rem;
|
||||
height: 2.875rem;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||
import paymentMethodListButton from './payment-method-list-button/payment-method-list-button.vue';
|
||||
import { markRaw } from 'vue';
|
||||
|
||||
export default {
|
||||
name: 'payment-method-question',
|
||||
|
|
@ -33,7 +34,7 @@ export default {
|
|||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
paymentMethodListButton
|
||||
paymentMethodListButton: markRaw(paymentMethodListButton)
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
|
|||
|
|
@ -12,21 +12,24 @@
|
|||
</div>
|
||||
<div class="iss-heritage-container-width">
|
||||
<div class="payment-method-container iss-heritage-content-container-width">
|
||||
<alert
|
||||
class=""
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="AlertIncompleteWidget" />
|
||||
<siteSubHeader
|
||||
class="mb-5 mt-4 px-3"
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
secondaryTextClasses="text-center"
|
||||
subHeaderClasses="mt-4" />
|
||||
class="subheader"
|
||||
cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<div class="main-content-container">
|
||||
<hr class="my-0" />
|
||||
<hr class="section-divider" />
|
||||
<reviewDropdown ref="reviewDropdown" />
|
||||
<hr class="my-0" />
|
||||
<hr class="section-divider" />
|
||||
<textBlock
|
||||
cmsWidgetName="CartHeaderWidget" />
|
||||
<cartDropdown
|
||||
:showAsPaid="false"
|
||||
:readOnly="false"
|
||||
recyclingModalCmsWidgetName="RecycleModal"
|
||||
servicePackageTitleWidgetName="ServicePackageTitle" />
|
||||
<hr class="mt-0 mb-5" />
|
||||
<alert
|
||||
v-if="displayPayInAdvanceAlert"
|
||||
name="payInAdvanceErrorAlert"
|
||||
|
|
@ -34,6 +37,9 @@
|
|||
cmsWidgetName="PayInAdvanceErrorAlertWidget"
|
||||
alertClass="alert-danger"
|
||||
:isDismissible="false" />
|
||||
<hr
|
||||
v-if="!isPayInAdvanceDisabled"
|
||||
class="pia-divider" />
|
||||
<paymentMethodQuestion
|
||||
v-if="!isPayInAdvanceDisabled"
|
||||
v-model="paymentMethod"
|
||||
|
|
@ -69,6 +75,7 @@ import reviewDropdown from '@/layouts/payment-method/review-dropdown/review-drop
|
|||
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
|
||||
import paymentMethodQuestion from '@/layouts/payment-method/payment-method-question/payment-method-question.vue';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||
|
||||
// Supporting Items
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
|
|
@ -97,7 +104,8 @@ export default {
|
|||
reviewDropdown,
|
||||
cartDropdown,
|
||||
paymentMethodQuestion,
|
||||
alert
|
||||
alert,
|
||||
textBlock
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -137,9 +145,8 @@ export default {
|
|||
customCallToActionButtonCopy() {
|
||||
switch (this.paymentMethod) {
|
||||
case paymentMethods.PayNow:
|
||||
return 'Continue to checkout';
|
||||
case paymentMethods.AFTERPAY:
|
||||
return 'Continue to Afterpay';
|
||||
return 'Continue to checkout';
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
|
|
@ -304,20 +311,49 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
$page-side-padding: 1.5rem;
|
||||
.iss-heritage-container-width {
|
||||
#app .iss-heritage-container-width {
|
||||
.iss-heritage-content-container-width {
|
||||
@include media-breakpoint-up(md) {
|
||||
width: 58.33333333%;
|
||||
}
|
||||
}
|
||||
.payment-method-container {
|
||||
position: relative;
|
||||
min-height: 1px;
|
||||
padding-left: .9375rem;
|
||||
padding-right: .9375rem;
|
||||
|
||||
.alert-warning {
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
|
||||
.subheader {
|
||||
margin-top: 1.25rem;
|
||||
|
||||
:deep(strong) {
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.subheader-secondary) {
|
||||
margin-top: .625rem;
|
||||
|
||||
p {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-divider {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 1.875rem;
|
||||
}
|
||||
|
||||
.pia-divider {
|
||||
margin-top: .5rem;
|
||||
margin-bottom: .75rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-content-container {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.page-container-grouped-styles {
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div :class="[isExpanded ? 'pb-3' : 'pb-4']">
|
||||
<div>
|
||||
<div
|
||||
class="row review-toggle flex align-items-center pt-4"
|
||||
class="row review-toggle flex align-items-center"
|
||||
:class="[isExpanded ? 'expanded' : '']"
|
||||
@click="toggleIsExpanded">
|
||||
<a
|
||||
|
|
@ -15,12 +15,12 @@
|
|||
<vehicleReview
|
||||
cmsWidgetName="VehicleReviewWidget"
|
||||
:vehicle="vehicleInfo" />
|
||||
<hr class="my-0" />
|
||||
<hr class="review-divider" />
|
||||
<damageReview
|
||||
cmsWidgetName="DamageReviewWidget"
|
||||
damageLocationsWidgetName="DamageLocationsWidget"
|
||||
:damage="damageInfo" />
|
||||
<hr class="my-0" />
|
||||
<hr class="review-divider" />
|
||||
<servicePackageReview
|
||||
ref="servicePackageReview"
|
||||
servicePackageOptionsCmsName="ServicePackageTitle"
|
||||
|
|
@ -28,15 +28,15 @@
|
|||
vapsItemsCmsName="VapsItemDescriptions"
|
||||
:damage="damageInfo"
|
||||
:lineItems="lineItems" />
|
||||
<hr class="my-0" />
|
||||
<hr class="review-divider" />
|
||||
<serviceLocationReview
|
||||
cmsWidgetName="ServiceLocationTitleWidget"
|
||||
:serviceLocation="serviceLocationInfo" />
|
||||
<hr class="my-0" />
|
||||
<hr class="review-divider" />
|
||||
<scheduleReview
|
||||
cmsWidgetName="ScheduleWidget"
|
||||
:appointmentType="appointmentType" />
|
||||
<hr class="my-0" />
|
||||
<hr class="review-divider" />
|
||||
<customerReview
|
||||
cmsWidgetName="CustomerReviewWidget"
|
||||
:customer="customerInfo" />
|
||||
|
|
@ -121,12 +121,13 @@ export default {
|
|||
.review-toggle {
|
||||
&:after {
|
||||
content: "";
|
||||
transition: all 0.5s ease;
|
||||
background-image: url($svg-payment-method-review-toggle);
|
||||
transition: transform none;
|
||||
background-image: url(~@/assets/img/icons/chevron-circle_review_dropdown.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
width: 16px;
|
||||
height: 9px;
|
||||
background-size: 1.25rem 1.25rem;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
right: 0.75rem;
|
||||
|
|
|
|||
Loading…
Reference in a new issue