Merge branch 'develop' into feature/digital/SSR-512-2

# Conflicts:
#	src/store/index.js
This commit is contained in:
Josh Dassinger 2024-02-29 09:05:36 -06:00
commit d8e0f575ef
12 changed files with 823 additions and 141 deletions

View file

@ -99,6 +99,10 @@ const endpoints = Object.freeze({
url: '/vehicle/api/v1/vehicle/lookup', url: '/vehicle/api/v1/vehicle/lookup',
method: 'GET' method: 'GET'
}, },
GetAccountInfo: {
url: '/account/api/v1/account/',
method: 'GET'
},
LogExperimentExposureIfAssigned: { LogExperimentExposureIfAssigned: {
url: '/experiments/api/v1/experiments/log-exposure', url: '/experiments/api/v1/experiments/log-exposure',
method: 'POST' method: 'POST'

View file

@ -0,0 +1,11 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`cart-dropdown component initial data rendered as expected 1`] = `
Object {
"currencyFormatter": NumberFormat {},
"isExpanded": false,
"widget": Object {
"amountDue": "AmountDueTextWidget",
},
}
`;

View file

@ -0,0 +1,159 @@
import { shallowMount } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
// Supporting Files
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import { useMainStore } from '@/store';
function getMountedComponent(mainInitialState = {}, initialData = {}, propsData = {}) {
const mountOptions = getMountOptions({
router: {
navigate: jest.fn()
}
});
const testingPinia = createTestingPinia({
initialState: {
main: mainInitialState
}
});
useMainStore(testingPinia);
mountOptions.global.plugins = [testingPinia];
mountOptions.data = () => (initialData);
mountOptions.propsData = propsData;
const wrapper = shallowMount(cartDropdown, mountOptions);
wrapper.vm.getCmsContent = jest.fn().mockImplementation(() => {});
wrapper.vm.setCmsContent = jest.fn();
return { wrapper };
}
describe('cart-dropdown component', () => {
test('initial data rendered as expected', () => {
// Arrange
const { wrapper } = getMountedComponent();
// Assert
expect(wrapper.vm.$data).toMatchSnapshot();
});
describe('displays', () => {
test('cart dropdown head', () => {
// Arrange
const reference = '#cart-dropdown-head';
const { wrapper } = getMountedComponent(cartDropdown);
// Act
const head = wrapper.find(reference);
// Assert
expect(head.exists()).toBeTruthy();
});
test('cart table', () => {
// Arrange
const reference = '#cart-table';
const isExpanded = true;
const initialData = { isExpanded };
const { wrapper } = getMountedComponent(cartDropdown, {}, initialData);
// Act
const cartTable = wrapper.find(reference);
// Assert
expect(cartTable.exists()).toBeTruthy();
});
});
describe('computed', () => {
test.each([
[true, true],
[false, false],
[false, null]
])('isVerified returns %p when isVerified store value is %p', (expected, isVerified) => {
// Arrange
const storeData = {
order: {
payment: {
insuranceCoverage: { isVerified }
}
}
};
const { wrapper } = getMountedComponent(storeData);
// Act
const result = wrapper.vm.isVerified;
// Assert
expect(result).toBe(expected);
});
describe('amountDueDisplayed', () => {
test('returns verifying coverage text when isVerified false', () => {
// Arrange
const VERIFYING_COVERAGE = 'Verifying coverage';
const storeData = {
order: {
payment: {
insuranceCoverage: {
isVerified: false
}
}
}
};
const { wrapper } = getMountedComponent(storeData);
// Act
const result = wrapper.vm.amountDueDisplayed;
// Assert
expect(result).toBe(VERIFYING_COVERAGE);
});
test('returns formatted amount due when isVerified false', () => {
// TODO finish when methods done
});
});
describe('amountDue', () => {
test('returns 0 when showAsPaid is true', () => {
// Arrange
const propsData = {
showAsPaid: true
};
const { wrapper } = getMountedComponent({}, {}, propsData);
// Act
const result = wrapper.vm.amountDue;
// Assert
expect(result).toBe(0);
});
test('returns sum of subTotal and salesTax when showAsPaid is false', () => {
// TODO when subTotal and salesTax are finished
});
});
describe('subTotal', () => {
// TODO when method implemented
});
describe('salesTax', () => {
// TODO when method implemented
});
});
describe('method', () => {
test.each([
['$0.00', 0],
['$12.00', 12],
['$12.30', 12.3],
['$12.34', 12.34],
['$12.35', 12.345],
['$12.34', 12.344],
['-$1.00', -1]
])('get FormattedAmount returns `%` when amount %', (expected, amount) => {
// Arrange
const { wrapper } = getMountedComponent();
// Act
const result = wrapper.vm.getFormattedAmount(amount);
// Assert
expect(result).toBe(expected);
});
});
});

View file

@ -0,0 +1,131 @@
<template>
<div :class="[isExpanded ? 'pb-3' : 'pb-4']">
<div
id="cart-dropdown-head"
class="row cart-toggle flex align-items-center pt-4"
:class="[isExpanded ? 'expanded' : '']"
@click="toggleIsExpanded">
<a
aria-label="expand cart details"
href="javascript:void(0)"
class="col d-flex justify-content-between py-0">
<span class="label color-black">{{ amountDueLabel }}</span>
<span class="label amount-due">{{ amountDueDisplayed }}</span>
</a>
</div>
<div
id="cart-table"
class="cart-table px-4">
<span>Cart Table Placeholder</span>
</div>
</div>
</template>
<script>
import { useMainStore } from '@/store';
const VERIFYING_COVERAGE = 'Verifying coverage';
export default {
name: 'cart-dropdown',
components: {},
props: {
showAsPaid: Boolean,
amountDueLabel: String
},
data() {
return {
isExpanded: false,
currencyFormatter: new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}),
widget: {
amountDue: 'AmountDueTextWidget'
}
};
},
computed: {
isVerified() {
return useMainStore().payment?.insuranceCoverage?.isVerified ?? false;
},
amountDueDisplayed() {
return this.isVerified
? this.getFormattedAmount(this.amountDue)
: VERIFYING_COVERAGE;
},
amountDue() {
return this.showAsPaid
? 0
: this.subTotal + this.salesTax;
},
subTotal() {
return 0;
},
salesTax() {
return 0;
}
},
methods: {
toggleIsExpanded() {
this.isExpanded = !this.isExpanded;
},
getFormattedAmount(amount) {
return this.currencyFormatter.format(amount);
}
}
};
</script>
<style lang="scss" scoped>
@import "@/styles/ux-variables-svg-strings.scss";
.color-black {
color: $black;
}
.cart-table {
max-height: 0;
transition: all 350ms ease-in;
overflow: hidden;
visibility: hidden;
}
.cart-toggle {
.amount-due {
color: $green;
}
&:after {
content: "";
transition: all 0.5s ease;
background-image: url($svg-payment-method-review-toggle);
background-repeat: no-repeat;
background-position: right center;
width: 1rem;
height: 0.5625rem;
display: inline-flex;
position: relative;
right: 0.75rem;
margin: 0.5rem 0 0.5rem 1rem;
cursor: pointer;
}
&.expanded:after {
transform: rotate(180deg);
}
&.expanded + .cart-table {
max-height: 50rem;
transition: all 150ms ease-in;
overflow: hidden;
visibility: visible;
}
a {
text-decoration: none;
}
.label {
font-weight: $font-weight-bold;
line-height: 1.625;
}
}
</style>

View file

@ -0,0 +1,131 @@
// Components
import orderConfirmation from '@/layouts/order-confirmation/order-confirmation.vue';
// Supporting Files
import { getMountOptions } from '@/helpers/unit-test-helper.js';
import { useMainStore } from '@/store/index.js';
import settleAllPromises from '@/helpers/layout-helper.js';
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import { mount } from '@vue/test-utils';
import { createTestingPinia } from '@pinia/testing';
jest.mock('@/helpers/layout-helper.js', () => jest.fn());
jest.mock('@/helpers/cms-content-helper', () => ({
fetchCmsContentForPage: jest.fn()
}));
const mockMixin = {
methods: {
getCmsContent: jest.fn().mockImplementation(() => ''),
setCmsContent: jest.fn()
}
};
const footerStub = {
render: () => {},
methods: {
updateButtonText: jest.fn()
}
};
const headerStub = {
render: () => {}
};
function getMountedComponent(mainInitialState = {}, initialData = {}, methodToRun = () => {}) {
const mountOptions = getMountOptions({
router: {
navigate: jest.fn(),
navigateToExternalUrl: jest.fn()
}
});
mountOptions.global.stubs = {
siteFooter: footerStub,
siteHeader: headerStub
};
const testingPinia = createTestingPinia({
initialState: {
main: mainInitialState
}
});
useMainStore(testingPinia);
methodToRun();
mountOptions.global.plugins = [testingPinia];
mountOptions.mixins = [mockMixin];
mountOptions.data = () => (
initialData
);
const apiResponses = {
supportingItems: []
};
const apiPromise = Promise.resolve(apiResponses);
settleAllPromises.mockImplementation(() => apiPromise);
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
const wrapper = mount(orderConfirmation, mountOptions);
return { wrapper };
}
describe('OrderConfirmation.vue', () => {
describe('Rendering', () => {
test('Should render Site Header', () => {
// Arrange
const { wrapper } = getMountedComponent({});
// Act
const siteHeader = wrapper.findComponent(headerStub);
// Assert
expect(siteHeader.exists()).toBe(true);
});
test('If Advanced flow, should display Site Footer', () => {
// Arrange
const carrierReturnUrl = 'testURL';
const initialStore = {
issConfig: {
successReturnURL: carrierReturnUrl
}
};
const { wrapper } = getMountedComponent(initialStore);
// Act
const siteFooter = wrapper.findComponent({ ref: 'siteFooter' });
// Assert
expect(siteFooter.exists()).toBe(true);
});
test('If Essential flow, should not display Site Footer', () => {
// Arrange
const { wrapper } = getMountedComponent();
// Act
const siteFooter = wrapper.findComponent({ ref: 'siteFooter' });
// Assert
expect(siteFooter.isVisible()).toBe(false);
});
});
describe('Navigation', () => {
test('If Advanced flow, forward button action navigates to carrier URL', () => {
// Arrange
const carrierReturnUrl = 'testURL';
const initialStore = {
issConfig: {
successReturnURL: carrierReturnUrl
}
};
const { wrapper } = getMountedComponent(initialStore);
// Act
wrapper.vm.forwardButtonAction();
// Assert
expect(wrapper.vm.$router.navigateToExternalUrl).toHaveBeenCalledWith(carrierReturnUrl);
});
});
});

View file

@ -7,14 +7,16 @@
<div class="page-container-grouped-styles"> <div class="page-container-grouped-styles">
<div class="fade-on-route-transition position-relative"> <div class="fade-on-route-transition position-relative">
<siteHeader cmsWidgetName="SiteHeaderWidget" /> <siteHeader cmsWidgetName="SiteHeaderWidget" />
<div class="container-fluid pb-2"> <div class="main-content-container">
<p>Placeholder for order confirmation page</p> <p>Placeholder for order confirmation page</p>
<siteFooter <siteFooter
ref="siteFooter" v-if="carrierUrl"
cmsWidgetName="SiteFooterWidget" ref="siteFooter"
:isForwardActionDisabled="!meta.valid" cmsWidgetName="SiteFooterWidget"
@ForwardClicked="forwardButtonAction" :isStackedVertically="true"
@backClicked="navigateBack" /> :isForwardActionDisabled="!meta.valid"
@ForwardClicked="forwardButtonAction"
@backClicked="navigateBack" />
</div> </div>
</div> </div>
</div> </div>
@ -29,6 +31,7 @@ import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import settleAllPromises from '@/helpers/layout-helper'; import settleAllPromises from '@/helpers/layout-helper';
import { Form } from 'vee-validate'; import { Form } from 'vee-validate';
import BaseFormMixin from '@/mixins/base-form-mixin.js'; import BaseFormMixin from '@/mixins/base-form-mixin.js';
import { useMainStore } from '@/store';
export default { export default {
name: 'order-confirmation', name: 'order-confirmation',
@ -54,17 +57,38 @@ export default {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
}); });
}, },
methods: setup() {
{ const mainStore = useMainStore();
forwardButtonAction() { return { mainStore };
return this.navigateForward(); },
}, computed: {
navigateForward() { carrierName() {
this.$router.navigate( return this.mainStore.issConfig.clientName;
this.navigationScenarios.CLICKED_FORWARD, },
this.$route carrierUrl() {
); return this.mainStore.issConfig.successReturnURL;
}
} }
},
mounted() {
if (this.carrierUrl) {
this.$refs.siteFooter.updateButtonText(`Go back to ${this.carrierName}`);
}
},
methods: {
forwardButtonAction() {
this.$router.navigateToExternalUrl(this.carrierUrl);
}
}
}; };
</script> </script>
<style lang="scss" scoped>
$page-side-padding: 1.5rem;
.page-container-grouped-styles {
overflow: auto;
.main-content-container {
padding: 0 1.5rem !important;
}
}
</style>

View file

@ -19,8 +19,10 @@
<hr class="my-0" /> <hr class="my-0" />
<reviewDropdown ref="reviewDropdown" /> <reviewDropdown ref="reviewDropdown" />
<hr class="my-0" /> <hr class="my-0" />
<div>Cart Placeholder</div> <cartDropdown
<hr class="my-5" /> :showAsPaid="false"
:amountDueLabel="amountDueText" />
<hr class="mt-0 mb-5" />
<div>Pia Alert Placeholder</div> <div>Pia Alert Placeholder</div>
<paymentMethodQuestion <paymentMethodQuestion
v-model="paymentMethodInternalModel" v-model="paymentMethodInternalModel"
@ -47,6 +49,7 @@ import siteHeader from '@/iss-components/site-header/site-header.vue';
import siteFooter from '@/iss-components/site-footer/site-footer.vue'; import siteFooter from '@/iss-components/site-footer/site-footer.vue';
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue'; import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
import reviewDropdown from '@/layouts/payment-method/review-dropdown/review-dropdown.vue'; import reviewDropdown from '@/layouts/payment-method/review-dropdown/review-dropdown.vue';
import cartDropdown from '@/iss-components/cart-dropdown/cart-dropdown.vue';
import paymentMethodQuestion from '@/layouts/payment-method/payment-method-question/payment-method-question.vue'; import paymentMethodQuestion from '@/layouts/payment-method/payment-method-question/payment-method-question.vue';
// Supporting Items // Supporting Items
@ -56,6 +59,7 @@ 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';
@ -68,6 +72,7 @@ export default {
siteSubHeader, siteSubHeader,
siteFooter, siteFooter,
reviewDropdown, reviewDropdown,
cartDropdown,
paymentMethodQuestion paymentMethodQuestion
}, },
mixins: [baseFormMixin], mixins: [baseFormMixin],
@ -102,6 +107,9 @@ export default {
paymentMethodInternalModel: this.getPaymentMethodFromStore(), paymentMethodInternalModel: this.getPaymentMethodFromStore(),
rules: { rules: {
optionRequired: globalRules.OPTION_REQUIRED optionRequired: globalRules.OPTION_REQUIRED
},
widget: {
amountDue: 'AmountDueTextWidget'
} }
}; };
}, },
@ -123,6 +131,9 @@ export default {
}, },
paymentMethod() { paymentMethod() {
return this.paymentMethodInternalModel; return this.paymentMethodInternalModel;
},
amountDueText() {
return this.getCmsContent(this.widget.amountDue, widgetFields.TEXT_BLOCK_WIDGET.TEXT);
} }
}, },
watch: { watch: {

View file

@ -1,5 +1,5 @@
<template> <template>
<div> <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 pt-4"
:class="[isExpanded ? 'expanded' : '']" :class="[isExpanded ? 'expanded' : '']"
@ -134,12 +134,6 @@ export default {
} }
.review-toggle { .review-toggle {
margin-bottom: 1rem;
&.expanded {
margin-bottom: 0;
}
&:after { &:after {
content: ""; content: "";
transition: all 0.5s ease; transition: all 0.5s ease;

View file

@ -178,12 +178,11 @@ describe('payment-page.vue', () => {
}, },
techNotes: '' techNotes: ''
}, },
customer: { contactInfo: {
firstName: 'first', firstName: 'first',
lastName: 'last', lastName: 'last',
emailAddress: 'builddigitaltest@safelite.com', emailAddress: 'builddigitaltest@safelite.com',
phoneNumber: '555-555-5555', phoneNumber: '555-555-5555'
isSmsOptIn: false
}, },
damage: { damage: {
isRepair: false, isRepair: false,

View file

@ -38,71 +38,191 @@
</Form> </Form>
<form <form
ref="hopForm"
id="card-data" id="card-data"
ref="hopForm"
:target="isPaypal ? '_top' : 'card-frame'" :target="isPaypal ? '_top' : 'card-frame'"
method="POST" method="POST"
:action="checkoutUrl"> :action="checkoutUrl">
<input type="hidden" name="paymentType" :value="paymentType" /> <input
<input type="hidden" name="sgSessionId" :value="authToken" /> type="hidden"
<input type="hidden" name="sgAuthToken" :value="authToken" /> name="paymentType"
<input type="hidden" name="sgSignaturePublic" :value="authSignature" /> :value="paymentType" />
<input type="hidden" name="sgSignatureStartDate" :value="authSignatureStart" /> <input
<input type="hidden" name="referralSeqNum" :value="referralSequenceNumber" /> type="hidden"
name="sgSessionId"
<input type="hidden" name="sge_commerce_indicator_isinternet" value="true" /> :value="authToken" />
<input type="hidden" name="sghopsource" value="Safelite.com" /> <input
<input type="hidden" name="sgHtmlStyle" value="ResourceSafeliteHtml" /> type="hidden"
<input type="hidden" name="sgErrorMessagesEmbedded" value="true" /> name="sgAuthToken"
:value="authToken" />
<input type="hidden" name="sgNoKeystrokeProcessing" value="false" /> <input
type="hidden"
<input type="hidden" name="maskCharacter" value="*" /> name="sgSignaturePublic"
<input type="hidden" name="styleSheetCode" :value="dynamicCSSUrl" /> :value="authSignature" />
<input type="hidden" name="styleSheetCode2" :value="dynamicHopCSSUrl" /> <input
type="hidden"
<input type="hidden" name="sgReceiptResponseURL" :value="payInAdvanceResponseUrl" /> name="sgSignatureStartDate"
<input type="hidden" name="sgDeclineResponseURL" :value="payInAdvanceResponseUrl" /> :value="authSignatureStart" />
<input type="hidden" name="sgErrorResponseURL" :value="payInAdvanceResponseUrl" /> <input
type="hidden"
<input type="hidden" name="sgheaderline1" :value="getHeaderLine1" /> name="referralSeqNum"
<input type="hidden" name="sgHeader1subtitle" value="" /> :value="referralSequenceNumber" />
<input type="hidden" name="sgheaderline2" :value="getHeaderLine2" /> <input
<input type="hidden" name="sgheaderline3" value="" /> type="hidden"
<input type="hidden" name="sgheaderline4" value="" /> name="sge_commerce_indicator_isinternet"
<input type="hidden" name="sgheaderline5" value="*Required information" /> value="true" />
<input
<input type="hidden" name="billTo_firstName" :value="firstName" /> type="hidden"
<input type="hidden" name="billTo_firstNameShow" value="true" /> name="sghopsource"
<input type="hidden" name="sghopmiddleInitialShow" value="false" /> value="Safelite.com" />
<input type="hidden" name="billTo_lastName" :value="lastName" /> <input
<input type="hidden" name="billTo_lastNameShow" value="true" /> type="hidden"
name="sgHtmlStyle"
<input type="hidden" name="billTo_street1" value="" /> value="ResourceSafeliteHtml" />
<input type="hidden" name="billTo_street2" value="" /> <input
<input type="hidden" name="billTo_city" value="" /> type="hidden"
<input type="hidden" name="billTo_state" value="" /> name="sgErrorMessagesEmbedded"
value="true" />
<input type="hidden" name="billTo_postalCode" value="" /> <input
<input type="hidden" name="billTo_postalCodeShow" value="true" /> type="hidden"
<input type="hidden" name="billTo_postalCodeEnable" value="true" /> name="sgNoKeystrokeProcessing"
<input type="hidden" name="sgLabelPostalCode" value="Billing ZIP" /> value="false" />
<input
<input type="hidden" name="sgtotalamount" :value="displayAmount" /> type="hidden"
<input type="hidden" name="totalAmountDecimal" :value="totalAmount" /> name="maskCharacter"
<input type="hidden" name="lineItems" :value="payInAdvanceLineItems" /> value="*" />
<input
<input type="hidden" name="sgdiscountstrikethruamount" value="" /> type="hidden"
name="styleSheetCode"
<input type="hidden" name="callerDisplayText" value="" /> :value="dynamicCSSUrl" />
<input
type="hidden"
name="styleSheetCode2"
:value="dynamicHopCSSUrl" />
<input
type="hidden"
name="sgReceiptResponseURL"
:value="payInAdvanceResponseUrl" />
<input
type="hidden"
name="sgDeclineResponseURL"
:value="payInAdvanceResponseUrl" />
<input
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="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 <input
type="hidden" type="hidden"
name="sgtermsofusedisplaytext" name="sgtermsofusedisplaytext"
value="By selecting submit, I agree to Safelite's" /> value="By selecting submit, I agree to Safelite's" />
<input type="hidden" name="sgtermsofuseurl" value="http://www.safelite.com/terms-of-use/" /> <input
<input type="hidden" name="sgtermsofuselinkdisplaytext" value="terms of use" /> type="hidden"
<input type="hidden" name="sgtermsofcancelrefunddisplaytext" value="and" /> name="sgtermsofuseurl"
value="http://www.safelite.com/terms-of-use/" />
<input
type="hidden"
name="sgtermsofuselinkdisplaytext"
value="terms of use" />
<input
type="hidden"
name="sgtermsofcancelrefunddisplaytext"
value="and" />
<input <input
type="hidden" type="hidden"
name="sgtermsofcancelrefundlinkdisplaytext" name="sgtermsofcancelrefundlinkdisplaytext"
@ -111,7 +231,6 @@
type="hidden" type="hidden"
name="sgtermsofcancelrefundurl" name="sgtermsofcancelrefundurl"
value="http://www.safelite.com/cancellation-refund-policy" /> value="http://www.safelite.com/cancellation-refund-policy" />
<input <input
type="hidden" type="hidden"
name="sgErrorMessageCardVerification" name="sgErrorMessageCardVerification"
@ -120,42 +239,122 @@
type="hidden" type="hidden"
name="sgErrorMessageTimeOut" name="sgErrorMessageTimeOut"
value="For your security, this transaction has been timed out." /> value="For your security, this transaction has been timed out." />
<input
<input type="hidden" name="sgLabelCardNumber" value="" /> type="hidden"
<input type="hidden" name="sgLabelAddressLine1" :value="address1" /> name="sgLabelCardNumber"
<input type="hidden" name="sgLabelAddressLine2" :value="address2" /> value="" />
<input type="hidden" name="sgLabelCity" :value="city" /> <input
<input type="hidden" name="sgLabelState" :value="state" /> type="hidden"
name="sgLabelAddressLine1"
<input type="hidden" name="sgCtu" :value="ctu" /> :value="address1" />
<input type="hidden" name="sgWorkOrder" :value="workOrderNumber" /> <input
<input type="hidden" name="sgEmailAddress" :value="emailAddress" /> type="hidden"
<input type="hidden" name="paypalInvoiceNumber" :value="invoiceNumber" /> name="sgLabelAddressLine2"
<input type="hidden" name="paypalSuccessUrl" :value="payInAdvanceResponseUrl" /> :value="address2" />
<input type="hidden" name="paypalCancelUrl" :value="payInAdvanceCancelUrl" /> <input
type="hidden"
<input type="hidden" name="sgCCDeclineURL" :value="payInAdvanceCancelUrl" /> name="sgLabelCity"
<input type="hidden" name="sgCCTimeoutURL" :value="payInAdvanceCancelUrl" /> :value="city" />
<input
<input type="hidden" name="sgTransactionType" value="authorization" /> type="hidden"
<input type="hidden" name="amount" :value="totalAmount" /> name="sgLabelState"
<input type="hidden" name="ctu" :value="ctu" /> :value="state" />
<input type="hidden" name="orderNumber" :value="workOrderNumber" /> <input
type="hidden"
<input type="hidden" name="billTo_email" :value="emailAddress" /> name="sgCtu"
<input type="hidden" name="useDecisionManager" value="True" /> :value="ctu" />
<input type="hidden" name="correlationId" :value="referralCorrelationId" /> <input
<input type="hidden" name="sgErrorMessageCard_CVN" value="Please enter a valid CVV" /> type="hidden"
name="sgWorkOrder"
<input type="hidden" name="ship_to_address_line1" :value="address1" /> :value="workOrderNumber" />
<input type="hidden" name="ship_to_address_line2" :value="address2" /> <input
<input type="hidden" name="ship_to_address_city" :value="city" /> type="hidden"
<input type="hidden" name="ship_to_address_state" :value="state" /> name="sgEmailAddress"
<input type="hidden" name="ship_to_address_country" value="US" /> :value="emailAddress" />
<input type="hidden" name="ship_to_address_postal_code" :value="zipCode" /> <input
<input type="hidden" name="ship_to_phone" :value="phoneNumber" /> type="hidden"
name="paypalInvoiceNumber"
<input type="hidden" name="calling_application" value="ISSNextGen" /> :value="invoiceNumber" />
<input
type="hidden"
name="paypalSuccessUrl"
:value="payInAdvanceResponseUrl" />
<input
type="hidden"
name="paypalCancelUrl"
:value="payInAdvanceCancelUrl" />
<input
type="hidden"
name="sgCCDeclineURL"
:value="payInAdvanceCancelUrl" />
<input
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="correlationId"
:value="referralCorrelationId" />
<input
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_postal_code"
:value="zipCode" />
<input
type="hidden"
name="ship_to_phone"
:value="phoneNumber" />
<input
type="hidden"
name="calling_application"
value="ISSNextGen" />
</form> </form>
</template> </template>
<script> <script>
@ -239,15 +438,15 @@ export default {
authSignature: '', authSignature: '',
authSignatureStart: '', authSignatureStart: '',
referralSequenceNumber: useMainStore().order.referralSequenceNumber, referralSequenceNumber: useMainStore().order.referralSequenceNumber,
emailAddress: useMainStore().order.customer.emailAddress, emailAddress: useMainStore().order.contactInfo.emailAddress,
address1: this.getAddress1(), address1: this.getAddress1(),
address2: this.getAddress2(), address2: this.getAddress2(),
city: this.getCity(), city: this.getCity(),
state: this.getState(), state: this.getState(),
zipCode: this.getZipCode(), zipCode: this.getZipCode(),
firstName: useMainStore().order.customer.firstName, firstName: useMainStore().order.contactInfo.firstName,
lastName: useMainStore().order.customer.lastName, lastName: useMainStore().order.contactInfo.lastName,
phoneNumber: useMainStore().order.customer.phoneNumber, phoneNumber: useMainStore().order.contactInfo.phoneNumber,
ctu: useMainStore().order.serviceLocation.zipCodeCtu, ctu: useMainStore().order.serviceLocation.zipCodeCtu,
referralCorrelationId: useMainStore().order.referralCorrelationId, referralCorrelationId: useMainStore().order.referralCorrelationId,
workOrderNumber: this.getWorkOrderNumber(), workOrderNumber: this.getWorkOrderNumber(),
@ -336,13 +535,13 @@ export default {
&& schedule.jobMinMinutes && schedule.jobMinMinutes
); );
// Customer // Contact Info
const { customer } = useMainStore().order; const { contactInfo } = useMainStore().order;
const customerReqs = !!( const contactInfoReqs = !!(
customer.firstName contactInfo.firstName
&& customer.lastName && contactInfo.lastName
&& customer.phoneNumber && contactInfo.phoneNumber
&& customer.emailAddress && contactInfo.emailAddress
); );
const paymentMethodReqs = const paymentMethodReqs =
@ -354,7 +553,7 @@ export default {
&& serviceLocationReqs && serviceLocationReqs
&& isInsuranceSet && isInsuranceSet
&& scheduleReqs && scheduleReqs
&& customerReqs && contactInfoReqs
&& paymentMethodReqs && paymentMethodReqs
); );
}, },

View file

@ -57,6 +57,7 @@
v-if="carrierUrl" v-if="carrierUrl"
ref="siteFooter" ref="siteFooter"
cmsWidgetName="SiteFooterWidget" cmsWidgetName="SiteFooterWidget"
:isStackedVertically="true"
:isForwardActionDisabled="!meta.valid" :isForwardActionDisabled="!meta.valid"
@ForwardClicked="forwardButtonAction" @ForwardClicked="forwardButtonAction"
@backClicked="navigateBack" /> @backClicked="navigateBack" />
@ -99,13 +100,19 @@ export default {
async beforeRouteEnter(to, from, next) { async beforeRouteEnter(to, from, next) {
// Call APIs // Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage); const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
const accountInfoPromise = useMainStore().getCarrierAccountInfo();
// Settle promises and get results // Settle promises and get results
const promiseResultMap = [ const promiseResultMap = [
{ {
resultKey: 'cmsContent', resultKey: 'cmsContent',
promise: cmsContentPromise promise: cmsContentPromise
}]; },
// use resultMap to populate layout content. {
resultKey: 'accountInfo',
promise: accountInfoPromise
}
];
// use resultMap to populate layout content.
const resultMap = await settleAllPromises(promiseResultMap); const resultMap = await settleAllPromises(promiseResultMap);
next((vm) => { next((vm) => {
vm.setCmsContent(resultMap.cmsContent); vm.setCmsContent(resultMap.cmsContent);
@ -161,15 +168,14 @@ export default {
isVerified() { isVerified() {
return useMainStore().order.payment.insuranceCoverage.isVerified; return useMainStore().order.payment.insuranceCoverage.isVerified;
}, },
// TODO: Replace with actual carrier number when account service is ready
carrierPhoneNumber() {
return '800-000-0000';
},
carrierName() { carrierName() {
return this.mainStore.issConfig.clientName; return this.mainStore.issConfig.clientName;
}, },
carrierUrl() { carrierUrl() {
return this.mainStore.issConfig.successReturnURL; return this.mainStore.issConfig.successReturnURL;
},
carrierPhoneNumber() {
return this.toDisplayPhoneNumber(useMainStore().order.carrierPhoneNumber);
} }
}, },
mounted() { mounted() {

View file

@ -181,6 +181,7 @@ const getDefaultState = () => ({
workOrderNumber: null, workOrderNumber: null,
originalDeductible: null, originalDeductible: null,
currentDeductible: null, currentDeductible: null,
carrierPhoneNumber: null,
loadedFromDupeCheck: null, loadedFromDupeCheck: null,
loadedSessionClearedPreviousData: null loadedSessionClearedPreviousData: null
}, },
@ -933,6 +934,18 @@ export const useMainStore = defineStore({
}); });
}, },
getCarrierAccountInfo() {
return new Promise((resolve, reject) => {
globalMethods.callHttpClient({
method: endpoints.GetAccountInfo.method,
endpoint: endpoints.GetAccountInfo.url + this.issConfig.parentAccountNumber
}).then((response) => {
this.order.carrierPhoneNumber = response.data.phoneNumber;
return resolve(response.data);
}).catch((error) => reject(error));
});
},
async getSupportingItems() { async getSupportingItems() {
const glassPartsArray = this.order.lineItems.glassParts ?? []; const glassPartsArray = this.order.lineItems.glassParts ?? [];
const { carId } = this.order.vehicle; const { carId } = this.order.vehicle;