WIP Update markup for payment-page.

This commit is contained in:
Bryan Mauger 2024-04-17 09:54:44 -04:00
parent bbeec83585
commit f5ee919209

View file

@ -1,9 +1,13 @@
<template>
<Form>
<div class="page-container-grouped-styles">
<div class="fade-on-route-transition position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="container-fluid pb-2 payment">
<div class="container-fluid fade-on-route-transition">
<div class="row justify-content-center">
<div class="col-md-6 px-0 px-md-2">
<siteHeader cmsWidgetName="SiteHeaderWidget" />
</div>
</div>
<div class="row justify-content-center">
<div class="col-md-6 col-xl-4">
<alert
v-if="displayPayInAdvanceCreditCardAlert"
name="payInAdvanceCreditCardErrorAlert"
@ -42,7 +46,6 @@
@backClicked="backButtonAction" />
</div>
</div>
<div
v-if="shouldBlockInteraction"
class="ui-block"
@ -56,22 +59,10 @@
:target="isPaypal ? '_top' : 'card-frame'"
method="POST"
:action="checkoutUrl">
<input
type="hidden"
name="paymentType"
:value="paymentType" />
<input
type="hidden"
name="sgSessionId"
:value="authToken" />
<input
type="hidden"
name="sgAuthToken"
:value="authToken" />
<input
type="hidden"
name="sgSignaturePublic"
:value="authSignature" />
<input type="hidden" name="paymentType" :value="paymentType" />
<input type="hidden" name="sgSessionId" :value="authToken" />
<input type="hidden" name="sgAuthToken" :value="authToken" />
<input type="hidden" name="sgSignaturePublic" :value="authSignature" />
<input
type="hidden"
name="sgSignatureStartDate"
@ -84,34 +75,13 @@
type="hidden"
name="sge_commerce_indicator_isinternet"
value="true" />
<input
type="hidden"
name="sghopsource"
value="Safelite.com" />
<input
type="hidden"
name="sgHtmlStyle"
value="ResourceSafeliteHtml" />
<input
type="hidden"
name="sgErrorMessagesEmbedded"
value="true" />
<input
type="hidden"
name="sgNoKeystrokeProcessing"
value="false" />
<input
type="hidden"
name="maskCharacter"
value="*" />
<input
type="hidden"
name="styleSheetCode"
:value="dynamicCSSUrl" />
<input
type="hidden"
name="styleSheetCode2"
:value="dynamicHopCSSUrl" />
<input type="hidden" name="sghopsource" value="Safelite.com" />
<input type="hidden" name="sgHtmlStyle" value="ResourceSafeliteHtml" />
<input type="hidden" name="sgErrorMessagesEmbedded" value="true" />
<input type="hidden" name="sgNoKeystrokeProcessing" value="false" />
<input type="hidden" name="maskCharacter" value="*" />
<input type="hidden" name="styleSheetCode" :value="dynamicCSSUrl" />
<input type="hidden" name="styleSheetCode2" :value="dynamicHopCSSUrl" />
<input
type="hidden"
name="sgReceiptResponseURL"
@ -124,102 +94,33 @@
type="hidden"
name="sgErrorResponseURL"
:value="payInAdvanceResponseUrl" />
<input
type="hidden"
name="sgheaderline1"
:value="getHeaderLine1" />
<input
type="hidden"
name="sgHeader1subtitle"
value="" />
<input
type="hidden"
name="sgheaderline2"
:value="getHeaderLine2" />
<input
type="hidden"
name="sgheaderline3"
value="" />
<input
type="hidden"
name="sgheaderline4"
value="" />
<input type="hidden" name="sgheaderline1" :value="getHeaderLine1" />
<input type="hidden" name="sgHeader1subtitle" value="" />
<input type="hidden" name="sgheaderline2" :value="getHeaderLine2" />
<input type="hidden" name="sgheaderline3" value="" />
<input type="hidden" name="sgheaderline4" value="" />
<input
type="hidden"
name="sgheaderline5"
value="*Required information" />
<input
type="hidden"
name="billTo_firstName"
:value="firstName" />
<input
type="hidden"
name="billTo_firstNameShow"
value="true" />
<input
type="hidden"
name="sghopmiddleInitialShow"
value="false" />
<input
type="hidden"
name="billTo_lastName"
:value="lastName" />
<input
type="hidden"
name="billTo_lastNameShow"
value="true" />
<input
type="hidden"
name="billTo_street1"
value="" />
<input
type="hidden"
name="billTo_street2"
value="" />
<input
type="hidden"
name="billTo_city"
value="" />
<input
type="hidden"
name="billTo_state"
value="" />
<input
type="hidden"
name="billTo_postalCode"
value="" />
<input
type="hidden"
name="billTo_postalCodeShow"
value="true" />
<input
type="hidden"
name="billTo_postalCodeEnable"
value="true" />
<input
type="hidden"
name="sgLabelPostalCode"
value="Billing ZIP" />
<input
type="hidden"
name="sgtotalamount"
:value="displayAmount" />
<input
type="hidden"
name="totalAmountDecimal"
:value="totalAmount" />
<input
type="hidden"
name="lineItems"
:value="payInAdvanceLineItems" />
<input
type="hidden"
name="sgdiscountstrikethruamount"
value="" />
<input
type="hidden"
name="callerDisplayText"
value="" />
<input type="hidden" name="billTo_firstName" :value="firstName" />
<input type="hidden" name="billTo_firstNameShow" value="true" />
<input type="hidden" name="sghopmiddleInitialShow" value="false" />
<input type="hidden" name="billTo_lastName" :value="lastName" />
<input type="hidden" name="billTo_lastNameShow" value="true" />
<input type="hidden" name="billTo_street1" value="" />
<input type="hidden" name="billTo_street2" value="" />
<input type="hidden" name="billTo_city" value="" />
<input type="hidden" name="billTo_state" value="" />
<input type="hidden" name="billTo_postalCode" value="" />
<input type="hidden" name="billTo_postalCodeShow" value="true" />
<input type="hidden" name="billTo_postalCodeEnable" value="true" />
<input type="hidden" name="sgLabelPostalCode" value="Billing ZIP" />
<input type="hidden" name="sgtotalamount" :value="displayAmount" />
<input type="hidden" name="totalAmountDecimal" :value="totalAmount" />
<input type="hidden" name="lineItems" :value="payInAdvanceLineItems" />
<input type="hidden" name="sgdiscountstrikethruamount" value="" />
<input type="hidden" name="callerDisplayText" value="" />
<input
type="hidden"
name="sgtermsofusedisplaytext"
@ -252,38 +153,14 @@
type="hidden"
name="sgErrorMessageTimeOut"
value="For your security, this transaction has been timed out." />
<input
type="hidden"
name="sgLabelCardNumber"
value="" />
<input
type="hidden"
name="sgLabelAddressLine1"
:value="address1" />
<input
type="hidden"
name="sgLabelAddressLine2"
:value="address2" />
<input
type="hidden"
name="sgLabelCity"
:value="city" />
<input
type="hidden"
name="sgLabelState"
:value="state" />
<input
type="hidden"
name="sgCtu"
:value="ctu" />
<input
type="hidden"
name="sgWorkOrder"
:value="workOrderNumber" />
<input
type="hidden"
name="sgEmailAddress"
:value="emailAddress" />
<input type="hidden" name="sgLabelCardNumber" value="" />
<input type="hidden" name="sgLabelAddressLine1" :value="address1" />
<input type="hidden" name="sgLabelAddressLine2" :value="address2" />
<input type="hidden" name="sgLabelCity" :value="city" />
<input type="hidden" name="sgLabelState" :value="state" />
<input type="hidden" name="sgCtu" :value="ctu" />
<input type="hidden" name="sgWorkOrder" :value="workOrderNumber" />
<input type="hidden" name="sgEmailAddress" :value="emailAddress" />
<input
type="hidden"
name="paypalInvoiceNumber"
@ -304,30 +181,12 @@
type="hidden"
name="sgCCTimeoutURL"
:value="payInAdvanceCancelUrl" />
<input
type="hidden"
name="sgTransactionType"
value="authorization" />
<input
type="hidden"
name="amount"
:value="totalAmount" />
<input
type="hidden"
name="ctu"
:value="ctu" />
<input
type="hidden"
name="orderNumber"
:value="workOrderNumber" />
<input
type="hidden"
name="billTo_email"
:value="emailAddress" />
<input
type="hidden"
name="useDecisionManager"
value="True" />
<input type="hidden" name="sgTransactionType" value="authorization" />
<input type="hidden" name="amount" :value="totalAmount" />
<input type="hidden" name="ctu" :value="ctu" />
<input type="hidden" name="orderNumber" :value="workOrderNumber" />
<input type="hidden" name="billTo_email" :value="emailAddress" />
<input type="hidden" name="useDecisionManager" value="True" />
<input
type="hidden"
name="correlationId"
@ -336,38 +195,17 @@
type="hidden"
name="sgErrorMessageCard_CVN"
value="Please enter a valid CVV" />
<input
type="hidden"
name="ship_to_address_line1"
:value="address1" />
<input
type="hidden"
name="ship_to_address_line2"
:value="address2" />
<input
type="hidden"
name="ship_to_address_city"
:value="city" />
<input
type="hidden"
name="ship_to_address_state"
:value="state" />
<input
type="hidden"
name="ship_to_address_country"
value="US" />
<input type="hidden" name="ship_to_address_line1" :value="address1" />
<input type="hidden" name="ship_to_address_line2" :value="address2" />
<input type="hidden" name="ship_to_address_city" :value="city" />
<input type="hidden" name="ship_to_address_state" :value="state" />
<input type="hidden" name="ship_to_address_country" value="US" />
<input
type="hidden"
name="ship_to_address_postal_code"
:value="zipCode" />
<input
type="hidden"
name="ship_to_phone"
:value="phoneNumber" />
<input
type="hidden"
name="calling_application"
value="ISSNextGen" />
<input type="hidden" name="ship_to_phone" :value="phoneNumber" />
<input type="hidden" name="calling_application" value="ISSNextGen" />
</form>
</template>
<script>
@ -386,7 +224,10 @@ import { useMainStore } from '@/store';
import iframeResize from 'iframe-resizer/js/iframeResizer.js';
import externalUrls from '@/router/router-constants/externalUrl-values.js';
import widgetFields from '@/constants/cms-widget-fields.js';
import { hopPaymentMethods, paymentMethods } from '@/constants/payment-method-constants.js';
import {
hopPaymentMethods,
paymentMethods,
} from '@/constants/payment-method-constants.js';
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
import queryStrings from '@/constants/query-strings';
import alert from '@/ux-components/alert/alert.vue';
@ -398,7 +239,7 @@ export default {
siteFooter,
// eslint-disable-next-line vue/no-reserved-component-names
Form,
alert
alert,
},
directives: {
resize: {
@ -409,15 +250,16 @@ export default {
},
unmounted(el) {
el.iFrameResizer.removeListeners();
}
}
},
},
},
mixins: [BaseFormMixin],
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
const paymentSignaturePromise = await useMainStore().getPaymentSignature();
const paymentSignaturePromise =
await useMainStore().getPaymentSignature();
const wipersPromise = useMainStore().getWipers();
const rainDefensePromise = useMainStore().getRainDefense();
@ -426,20 +268,20 @@ export default {
const promiseResultMap = [
{
resultKey: 'cmsContent',
promise: cmsContentPromise
promise: cmsContentPromise,
},
{
resultKey: 'paymentSignature',
promise: paymentSignaturePromise
promise: paymentSignaturePromise,
},
{
resultKey: 'wipers',
promise: wipersPromise
promise: wipersPromise,
},
{
resultKey: 'rainDefense',
promise: rainDefensePromise
}
promise: rainDefensePromise,
},
];
// use resultMap to populate layout content.
@ -452,16 +294,28 @@ export default {
resultMap.rainDefense,
...supportingItems,
...resultMap.wipers,
...glassParts
...glassParts,
];
const availableVaps = [resultMap.rainDefense, ...resultMap.wipers];
const pricedLineItemsToTax = await useMainStore().priceOrderItemsAndSaveServerData(lineItemsToTax);
const taxedLineItems = await useMainStore().taxOrderItemsAndSaveServerData(pricedLineItemsToTax);
const pricedLineItemsToTax =
await useMainStore().priceOrderItemsAndSaveServerData(
lineItemsToTax
);
const taxedLineItems =
await useMainStore().taxOrderItemsAndSaveServerData(
pricedLineItemsToTax
);
// Match all line items to the line items as they are in the store
// and rebuild the original structure.
const taxLineItems = useMainStore().mapTaxedLineItemsToStoreFormat(taxedLineItems, lineItemsFromStore);
const taxedVaps = useMainStore().mapTaxedLineItemsToStoreFormat(taxedLineItems, availableVaps);
const taxLineItems = useMainStore().mapTaxedLineItemsToStoreFormat(
taxedLineItems,
lineItemsFromStore
);
const taxedVaps = useMainStore().mapTaxedLineItemsToStoreFormat(
taxedLineItems,
availableVaps
);
next((vm) => {
vm.setCmsContent(resultMap.cmsContent);
@ -508,7 +362,7 @@ export default {
totalAmount: this.getAmountDue(),
displayAmount: this.getDisplayAmountDue(),
payInAdvanceLineItems: '',
shouldBlockInteraction: false
shouldBlockInteraction: false,
};
},
computed: {
@ -530,13 +384,19 @@ export default {
},
getHeaderLine1() {
if (!this.isPaypal) {
return this.getCmsContent('PayInAdvanceHeaderLine1', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
return this.getCmsContent(
'PayInAdvanceHeaderLine1',
widgetFields.TEXT_BLOCK_WIDGET.TEXT
);
}
return '';
},
getHeaderLine2() {
if (!this.isPaypal) {
return this.getCmsContent('PayInAdvanceHeaderLine2', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
return this.getCmsContent(
'PayInAdvanceHeaderLine2',
widgetFields.TEXT_BLOCK_WIDGET.TEXT
);
}
return '';
},
@ -548,70 +408,75 @@ export default {
},
displayPayInAdvanceAfterPayAlert() {
return this.displayPayInAdvanceAlert(paymentMethods.AFTERPAY);
}
},
},
methods:
{
methods: {
arePagePrerequisitesValid() {
// Line Items
const packageReqs = !!useMainStore().order.lineItems.supportingItems;
const packageReqs =
!!useMainStore().order.lineItems.supportingItems;
// Service Location
const { serviceLocation } = useMainStore().order;
const mobileReqs = !!(
serviceLocation.address
&& serviceLocation.city
&& serviceLocation.state
&& serviceLocation.zipCode
serviceLocation.address &&
serviceLocation.city &&
serviceLocation.state &&
serviceLocation.zipCode
);
const providerLocation = serviceLocation.provider.address;
const dropOffInshopReqs = !!(
providerLocation.streetAddress
&& providerLocation.city
&& providerLocation.state
&& providerLocation.zipCode
providerLocation.streetAddress &&
providerLocation.city &&
providerLocation.state &&
providerLocation.zipCode
);
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE
|| serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
const isMobile =
serviceLocation.appointmentType ===
AppointmentTypeStrings.MOBILE ||
serviceLocation.appointmentType ===
AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
const serviceLocationReqs =
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
// Insurance
const isInsuranceSet = useMainStore().order.payment.isInsurance !== null;
const isInsuranceSet =
useMainStore().order.payment.isInsurance !== null;
// Schedule
const { schedule } = useMainStore().order;
const scheduleReqs = !!(
schedule.date
&& schedule.startTime
&& schedule.endTime
&& schedule.jobMaxMinutes
&& schedule.jobMinMinutes
schedule.date &&
schedule.startTime &&
schedule.endTime &&
schedule.jobMaxMinutes &&
schedule.jobMinMinutes
);
// Contact Info
const { contactInfo } = useMainStore().order;
const contactInfoReqs = !!(
contactInfo.firstName
&& contactInfo.lastName
&& contactInfo.servicePhone
&& contactInfo.emailAddress
contactInfo.firstName &&
contactInfo.lastName &&
contactInfo.servicePhone &&
contactInfo.emailAddress
);
const paymentMethodReqs =
useMainStore().order.payment.isPayInAdvance !== null
&& (useMainStore().order.payment.isPayInAdvance || !!useMainStore().order.payment.payInAdvanceType);
useMainStore().order.payment.isPayInAdvance !== null &&
(useMainStore().order.payment.isPayInAdvance ||
!!useMainStore().order.payment.payInAdvanceType);
return (
packageReqs
&& serviceLocationReqs
&& isInsuranceSet
&& scheduleReqs
&& contactInfoReqs
&& paymentMethodReqs
packageReqs &&
serviceLocationReqs &&
isInsuranceSet &&
scheduleReqs &&
contactInfoReqs &&
paymentMethodReqs
);
},
setData(taxedVaps, taxLineItems) {
@ -636,19 +501,32 @@ export default {
return undefined;
},
getAddress1() {
return useMainStore().order.serviceLocation.address ?? useMainStore().order.serviceLocation.provider.address.streetAddress;
return (
useMainStore().order.serviceLocation.address ??
useMainStore().order.serviceLocation.provider.address
.streetAddress
);
},
getAddress2() {
return useMainStore().order.serviceLocation.address2;
},
getCity() {
return useMainStore().order.serviceLocation.city ?? useMainStore().order.serviceLocation.provider.address.city;
return (
useMainStore().order.serviceLocation.city ??
useMainStore().order.serviceLocation.provider.address.city
);
},
getState() {
return useMainStore().order.serviceLocation.state ?? useMainStore().order.serviceLocation.provider.address.state;
return (
useMainStore().order.serviceLocation.state ??
useMainStore().order.serviceLocation.provider.address.state
);
},
getZipCode() {
return useMainStore().order.serviceLocation.zipCode ?? useMainStore().order.serviceLocation.provider.address.zipCode;
return (
useMainStore().order.serviceLocation.zipCode ??
useMainStore().order.serviceLocation.provider.address.zipCode
);
},
getPaymentType() {
switch (useMainStore().order.payment.payInAdvanceType) {
@ -664,13 +542,33 @@ export default {
},
getPayInAdvanceLineItems(cartItems) {
const { glassParts } = useMainStore().order.lineItems;
const lineItems = (glassParts === null)
? [this.getPayInAdvanceFormattedLineItem('Labor', 0, 1), this.getPayInAdvanceFormattedLineItem('Repair supplies', 0, 1)]
: [this.getPayInAdvanceFormattedLineItem('Parts and labor', 0, 1)];
const lineItems =
glassParts === null
? [
this.getPayInAdvanceFormattedLineItem('Labor', 0, 1),
this.getPayInAdvanceFormattedLineItem(
'Repair supplies',
0,
1
),
]
: [
this.getPayInAdvanceFormattedLineItem(
'Parts and labor',
0,
1
),
];
cartItems.forEach((item) => {
if (item.name !== null && item.category !== 'promos') {
lineItems.push(this.getPayInAdvanceFormattedLineItem(item.name, (item.salesTax + item.subTotal).toFixed(2), 1));
lineItems.push(
this.getPayInAdvanceFormattedLineItem(
item.name,
(item.salesTax + item.subTotal).toFixed(2),
1
)
);
}
});
@ -681,9 +579,19 @@ export default {
},
getMockPiaLineItems() {
let lineItems = [];
lineItems = [this.getPayInAdvanceFormattedLineItem('Parts and labor', 0, 1)];
lineItems.push(this.getPayInAdvanceFormattedLineItem('New wiper blades', 75.22, 1));
lineItems.push(this.getPayInAdvanceFormattedLineItem('Recycling', 37.60, 1));
lineItems = [
this.getPayInAdvanceFormattedLineItem('Parts and labor', 0, 1),
];
lineItems.push(
this.getPayInAdvanceFormattedLineItem(
'New wiper blades',
75.22,
1
)
);
lineItems.push(
this.getPayInAdvanceFormattedLineItem('Recycling', 37.6, 1)
);
this.payInAdvanceLineItems = lineItems.join('||');
},
@ -691,7 +599,9 @@ export default {
return baseMixin.methods.getAmountDue(useMainStore().lineItems);
},
getDisplayAmountDue() {
return baseMixin.methods.getDisplayAmountDue(useMainStore().lineItems);
return baseMixin.methods.getDisplayAmountDue(
useMainStore().lineItems
);
},
fetchSignatureInfo(signatureInfo) {
this.authToken = signatureInfo.token;
@ -708,10 +618,21 @@ export default {
if (iframe) {
iframe.onload = () => {
if (iframe.contentWindow) {
if (this.paymentType === hopPaymentMethods.CREDIT_CARD) {
iframe.contentWindow.postMessage('CreditCardChosen', '*');
} else if (this.paymentType === hopPaymentMethods.AFTERPAY) {
iframe.contentWindow.postMessage('afterpay', '*');
if (
this.paymentType ===
hopPaymentMethods.CREDIT_CARD
) {
iframe.contentWindow.postMessage(
'CreditCardChosen',
'*'
);
} else if (
this.paymentType === hopPaymentMethods.AFTERPAY
) {
iframe.contentWindow.postMessage(
'afterpay',
'*'
);
}
}
};
@ -730,7 +651,8 @@ export default {
},
setIFrameListener() {
window.addEventListener('message', (event) =>
this.handleIFrameContentWindowMessage(event));
this.handleIFrameContentWindowMessage(event)
);
},
setUIBlock(val) {
this.shouldBlockInteraction = val;
@ -742,7 +664,8 @@ export default {
},
displayPayInAdvanceAlert(payMethod) {
return (
this.$route.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT] === payMethod
this.$route.query[queryStrings.DISPLAY_PAY_IN_ADVANCE_ALERT] ===
payMethod
);
},
paymentFailedPayLater() {
@ -756,14 +679,17 @@ export default {
window.location = this.payInAdvanceCancelUrl;
},
forwardButtonAction() {
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD, this.$route);
}
}
this.$router.navigate(
this.navigationScenarios.CLICKED_FORWARD,
this.$route
);
},
},
};
</script>
<style lang="scss" scoped>
.payment p{
margin-bottom:0.75rem;
.payment p {
margin-bottom: 0.75rem;
}
.hop-iframe {