Merge branch 'develop' into feature/Digital/CSR-1417
This commit is contained in:
commit
ff339a124b
44 changed files with 1086 additions and 255 deletions
|
|
@ -97,9 +97,7 @@ stages:
|
||||||
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
||||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||||
__VUE_APP_SAFELITE_HOP___: $(__VUE_APP_SAFELITE_HOP__)
|
__VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
|
||||||
__VUE_APP_PAYPAL_SUCCESS_URL__: $(__VUE_APP_PAYPAL_SUCCESS_URL__)
|
|
||||||
__VUE_APP_PAYPAL_CANCEL_URL__: $(__VUE_APP_PAYPAL_CANCEL_URL__)
|
|
||||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||||
__VUE_APP_MY_ACCOUNT__: $(__VUE_APP_MY_ACCOUNT__)
|
__VUE_APP_MY_ACCOUNT__: $(__VUE_APP_MY_ACCOUNT__)
|
||||||
indexDeployVariables:
|
indexDeployVariables:
|
||||||
|
|
@ -158,9 +156,7 @@ stages:
|
||||||
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
||||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||||
__VUE_APP_SAFELITE_HOP___: $(__VUE_APP_SAFELITE_HOP__)
|
__VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
|
||||||
__VUE_APP_PAYPAL_SUCCESS_URL__: $(__VUE_APP_PAYPAL_SUCCESS_URL__)
|
|
||||||
__VUE_APP_PAYPAL_CANCEL_URL__: $(__VUE_APP_PAYPAL_CANCEL_URL__)
|
|
||||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||||
__VUE_APP_MY_ACCOUNT__: $(__VUE_APP_MY_ACCOUNT__)
|
__VUE_APP_MY_ACCOUNT__: $(__VUE_APP_MY_ACCOUNT__)
|
||||||
indexDeployVariables:
|
indexDeployVariables:
|
||||||
|
|
@ -219,9 +215,7 @@ stages:
|
||||||
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
||||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||||
__VUE_APP_SAFELITE_HOP___: $(__VUE_APP_SAFELITE_HOP__)
|
__VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
|
||||||
__VUE_APP_PAYPAL_SUCCESS_URL__: $(__VUE_APP_PAYPAL_SUCCESS_URL__)
|
|
||||||
__VUE_APP_PAYPAL_CANCEL_URL__: $(__VUE_APP_PAYPAL_CANCEL_URL__)
|
|
||||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||||
indexDeployVariables:
|
indexDeployVariables:
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||||
|
|
@ -279,9 +273,7 @@ stages:
|
||||||
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
||||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||||
__VUE_APP_SAFELITE_HOP___: $(__VUE_APP_SAFELITE_HOP__)
|
__VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
|
||||||
__VUE_APP_PAYPAL_SUCCESS_URL__: $(__VUE_APP_PAYPAL_SUCCESS_URL__)
|
|
||||||
__VUE_APP_PAYPAL_CANCEL_URL__: $(__VUE_APP_PAYPAL_CANCEL_URL__)
|
|
||||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||||
indexDeployVariables:
|
indexDeployVariables:
|
||||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||||
|
|
|
||||||
|
|
@ -27,9 +27,9 @@ module.exports = {
|
||||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||||
coverageThreshold: {
|
coverageThreshold: {
|
||||||
global: {
|
global: {
|
||||||
statements: 78,
|
statements: 77,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit
|
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit
|
||||||
// silent: true,
|
silent: true,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,16 @@ const applicationConfig = {
|
||||||
SITE_ENTRY_TRIGGER_VALUE: "FixMyGlass",
|
SITE_ENTRY_TRIGGER_VALUE: "FixMyGlass",
|
||||||
CASH_PARENT_ACCOUNT_NUMBER: 167132,
|
CASH_PARENT_ACCOUNT_NUMBER: 167132,
|
||||||
MY_ACCOUNT: process.env.VUE_APP_MY_ACCOUNT,
|
MY_ACCOUNT: process.env.VUE_APP_MY_ACCOUNT,
|
||||||
|
PAYPAL_SUCCESS_URL:
|
||||||
|
location.protocol +
|
||||||
|
"//" +
|
||||||
|
location.host +
|
||||||
|
"/fmg/?fmgPage=payment-pia-return&src=concept-funnel",
|
||||||
|
PAYPAL_CANCEL_URL:
|
||||||
|
location.protocol +
|
||||||
|
"//" +
|
||||||
|
location.host +
|
||||||
|
"/fmg/?fmgPage=payment-method&src=concept-funnel",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { applicationConfig };
|
export { applicationConfig };
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ const experimentSettings = {
|
||||||
GOOGLE_CUSTOM_DIMENSION_INDEX: "Google Custom Dimension Index",
|
GOOGLE_CUSTOM_DIMENSION_INDEX: "Google Custom Dimension Index",
|
||||||
SUPPRESS_VIN_CAPTURE: "SuppressVinCapture",
|
SUPPRESS_VIN_CAPTURE: "SuppressVinCapture",
|
||||||
DISPLAY_AVAILABILITY_INDICATORS: "DisplayAvailabilityIndicators",
|
DISPLAY_AVAILABILITY_INDICATORS: "DisplayAvailabilityIndicators",
|
||||||
|
PIA_EXPERIENCE: "PIA Experience",
|
||||||
|
SUBMIT_ORDER_ENABLE_PIA: "SubmitOrder_Enable_PIA",
|
||||||
};
|
};
|
||||||
|
|
||||||
const experimentTriggers = {
|
const experimentTriggers = {
|
||||||
|
|
|
||||||
13
src/constants/payment-method-constants.js
Normal file
13
src/constants/payment-method-constants.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
export const paymentMethods = {
|
||||||
|
NONE: null,
|
||||||
|
LATER: "Later",
|
||||||
|
CREDIT_CARD: "CreditCard",
|
||||||
|
PAYPAL: "Paypal",
|
||||||
|
AFTERPAY: "Afterpay",
|
||||||
|
};
|
||||||
|
|
||||||
|
export const paymentTimes = {
|
||||||
|
NONE: null,
|
||||||
|
ADVANCE: "Advance",
|
||||||
|
LATER: "Later",
|
||||||
|
};
|
||||||
|
|
@ -87,6 +87,7 @@ const storeActions = {
|
||||||
SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes",
|
SAVE_SERVICE_LOCATION_TECH_NOTES: "saveServiceLocationTechNotes",
|
||||||
SAVE_WORK_ORDER_FLAG: "saveWorkOrderFlag",
|
SAVE_WORK_ORDER_FLAG: "saveWorkOrderFlag",
|
||||||
SAVE_PIA_ERROR_CODE: "savePiaErrorCode",
|
SAVE_PIA_ERROR_CODE: "savePiaErrorCode",
|
||||||
|
SAVE_PIA_WORK_ORDER: "savePiaWorkOrder",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { storeActions };
|
export { storeActions };
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
const storeMutations = {
|
const storeMutations = {
|
||||||
UPDATE_WORK_ORDER_FLAG: "updateWorkOrderFlag",
|
UPDATE_WORK_ORDER_FLAG: "updateWorkOrderFlag",
|
||||||
UPDATE_PIA_ERROR_CODE: "updatePiaErrorCode",
|
UPDATE_PIA_ERROR_CODE: "updatePiaErrorCode",
|
||||||
|
UPDATE_PIA_WORK_ORDER: "updatePiaWorkOrder",
|
||||||
|
|
||||||
// VEHICLE MUTATIONS
|
// VEHICLE MUTATIONS
|
||||||
UPDATE_YEAR: "updateYear",
|
UPDATE_YEAR: "updateYear",
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ export default {
|
||||||
classes = "d-flex flex-row p-0";
|
classes = "d-flex flex-row p-0";
|
||||||
break;
|
break;
|
||||||
case "listCard":
|
case "listCard":
|
||||||
classes = "row g-2 g-md-5 justify-content-center mb-1";
|
classes = "row g-2 g-md-5 justify-content-center mb-1 flex-nowrap";
|
||||||
if (this.isWide) {
|
if (this.isWide) {
|
||||||
classes += "flex-column";
|
classes += "flex-column";
|
||||||
}
|
}
|
||||||
|
|
@ -223,6 +223,10 @@ export default {
|
||||||
classes = "package-wrapper";
|
classes = "package-wrapper";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.buttonTypeString == "listCard" && this.buttonsInfo.length > 2) {
|
||||||
|
classes += " two-list-card-width";
|
||||||
|
}
|
||||||
|
|
||||||
return classes;
|
return classes;
|
||||||
},
|
},
|
||||||
buttonsInfo() {
|
buttonsInfo() {
|
||||||
|
|
@ -304,6 +308,10 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
|
.two-list-card-width {
|
||||||
|
width: 33.33333333%;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
.button-question-overflow {
|
.button-question-overflow {
|
||||||
height: calc(100vh - 274px);
|
height: calc(100vh - 274px);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,7 @@
|
||||||
loaderColor="blue"
|
loaderColor="blue"
|
||||||
loaderPosition="center" />
|
loaderPosition="center" />
|
||||||
<div class="row form-test-error" id="date-of-month-error">
|
<div class="row form-test-error" id="date-of-month-error">
|
||||||
<ErrorMessage name="date-of-month" class="small mt-1"></ErrorMessage>
|
<ErrorMessage :name="customComponentId" class="small mt-1"></ErrorMessage>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
v-if="calendarViewDirection === 'future' && !disableViewMoreDatesButton"
|
v-if="calendarViewDirection === 'future' && !disableViewMoreDatesButton"
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,6 @@ export default {
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
height: 100vh;
|
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.modal-body {
|
.modal-body {
|
||||||
|
|
@ -181,12 +180,16 @@ export default {
|
||||||
}
|
}
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
|
flex: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.modal-dialog-centered {
|
&.modal-dialog-centered {
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
align-items: inherit;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.modal-footer {
|
.modal-footer {
|
||||||
|
|
@ -195,6 +198,10 @@ export default {
|
||||||
button {
|
button {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
@include media-breakpoint-up(md) {
|
||||||
|
position: relative;
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.show .modal-dialog {
|
&.show .modal-dialog {
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ import addVapsButton from "./add-vaps-button/add-vaps-button";
|
||||||
export default {
|
export default {
|
||||||
name: "add-vaps-modal-buttons",
|
name: "add-vaps-modal-buttons",
|
||||||
props: {
|
props: {
|
||||||
cart: Object,
|
cartItems: Object,
|
||||||
rainDefenseItem: Object,
|
rainDefenseItem: Object,
|
||||||
wiperItems: Object,
|
wiperItems: Object,
|
||||||
vapsTilesCmsName: String,
|
vapsTilesCmsName: String,
|
||||||
|
|
@ -43,14 +43,14 @@ export default {
|
||||||
return this.showAddRainDefense || this.showAddWipers;
|
return this.showAddRainDefense || this.showAddWipers;
|
||||||
},
|
},
|
||||||
showAddRainDefense() {
|
showAddRainDefense() {
|
||||||
// if it's not found in the cart
|
// if not found in the cart
|
||||||
return !this.cart.some((vap) => {
|
return !this.cartItems.some((vap) => {
|
||||||
return vap.partType === "RAIN DEFENSE";
|
return vap.partType === "RAIN DEFENSE";
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
showAddWipers() {
|
showAddWipers() {
|
||||||
// if it's not found in the cart
|
// if not found in the cart
|
||||||
return !this.cart.some((vap) => {
|
return !this.cartItems.some((vap) => {
|
||||||
return vap.partType.includes(" WIPER");
|
return vap.partType.includes(" WIPER");
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
@click="toggleClass()">
|
@click="toggleClass()">
|
||||||
<div class="col d-flex justify-content-between">
|
<div class="col d-flex justify-content-between">
|
||||||
<span class="label">Amount Due</span
|
<span class="label">Amount Due</span
|
||||||
><span class="label amount-due">$321.00</span>
|
><span class="label amount-due">{{ amountDue }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="price-table">
|
<div class="price-table">
|
||||||
|
|
@ -19,7 +19,12 @@
|
||||||
:key="i"
|
:key="i"
|
||||||
:class="[this.displayedPackageLineItems ? 'vaps' : '']">
|
:class="[this.displayedPackageLineItems ? 'vaps' : '']">
|
||||||
<span>{{ lineItem.name }}</span>
|
<span>{{ lineItem.name }}</span>
|
||||||
<span><a href="#">Remove</a></span>
|
<textLink
|
||||||
|
ref="removeLink"
|
||||||
|
linkType="text"
|
||||||
|
text="showMoreShopsLinkText"
|
||||||
|
href="#!"
|
||||||
|
@click-event="removeItem(lineItem)" />
|
||||||
</div>
|
</div>
|
||||||
<hr style="background: red" />
|
<hr style="background: red" />
|
||||||
<div
|
<div
|
||||||
|
|
@ -27,7 +32,12 @@
|
||||||
:key="i"
|
:key="i"
|
||||||
:class="[this.displayedNonPackageLineItems ? 'vaps' : '']">
|
:class="[this.displayedNonPackageLineItems ? 'vaps' : '']">
|
||||||
<span>{{ lineItem.name }}</span>
|
<span>{{ lineItem.name }}</span>
|
||||||
<span><a href="#">Remove</a></span>
|
<textLink
|
||||||
|
ref="removeLink"
|
||||||
|
linkType="text"
|
||||||
|
text="showMoreShopsLinkText"
|
||||||
|
href="#!"
|
||||||
|
@click-event="removeItem(lineItem)" />
|
||||||
<span>{{ lineItem.price }}</span>
|
<span>{{ lineItem.price }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="hasRecycleLineItem">
|
<div v-if="hasRecycleLineItem">
|
||||||
|
|
@ -55,6 +65,7 @@ import {
|
||||||
findLineItemsWithPartType,
|
findLineItemsWithPartType,
|
||||||
} from "@/helpers/service-package-helper";
|
} from "@/helpers/service-package-helper";
|
||||||
import reviewBlock from "@/layouts/review/review-block/review-block";
|
import reviewBlock from "@/layouts/review/review-block/review-block";
|
||||||
|
import textLink from "@/ux-components/text-link/text-link";
|
||||||
import textBlock from "@/digital-components/text-block/text-block";
|
import textBlock from "@/digital-components/text-block/text-block";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -63,7 +74,7 @@ export default {
|
||||||
headerCmsWidgetName: String,
|
headerCmsWidgetName: String,
|
||||||
servicePackageOptionsCmsName: String,
|
servicePackageOptionsCmsName: String,
|
||||||
damage: Object,
|
damage: Object,
|
||||||
orderLineItems: Object,
|
storeLineItems: Object,
|
||||||
availableLineItems: Object,
|
availableLineItems: Object,
|
||||||
allowableCartItems: Object,
|
allowableCartItems: Object,
|
||||||
},
|
},
|
||||||
|
|
@ -73,6 +84,7 @@ export default {
|
||||||
//availableVaps: [], TO DO Do we need this?
|
//availableVaps: [], TO DO Do we need this?
|
||||||
packageWithVAPS: false,
|
packageWithVAPS: false,
|
||||||
// packageLevel: "",
|
// packageLevel: "",
|
||||||
|
amountDue: this.getAmountDue(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -110,7 +122,12 @@ export default {
|
||||||
|
|
||||||
return price;
|
return price;
|
||||||
},
|
},
|
||||||
//START HERE
|
getAmountDue() {
|
||||||
|
return baseMixin.methods.getDisplayAmountDue(this.storeLineItems);
|
||||||
|
},
|
||||||
|
removeItem(item) {
|
||||||
|
this.$emit("cart-remove", item);
|
||||||
|
},
|
||||||
getVapsLineItemsForSelectedPackage(packageName) {
|
getVapsLineItemsForSelectedPackage(packageName) {
|
||||||
const packageContentTypes = getPackageContents(
|
const packageContentTypes = getPackageContents(
|
||||||
this.glassToReplace,
|
this.glassToReplace,
|
||||||
|
|
@ -167,7 +184,7 @@ export default {
|
||||||
displayedPackageLineItems() {
|
displayedPackageLineItems() {
|
||||||
const displayedPackageLineItems = [];
|
const displayedPackageLineItems = [];
|
||||||
const packageLineItems = this.getVapsLineItemsForSelectedPackage(this.packageLevel);
|
const packageLineItems = this.getVapsLineItemsForSelectedPackage(this.packageLevel);
|
||||||
//TO DO Could we get the same list from this.orderLineItems?
|
//TO DO Could we get the same list from this.storeLineItems?
|
||||||
packageLineItems?.forEach((item) => {
|
packageLineItems?.forEach((item) => {
|
||||||
let price = item.sellingPrice + item.kitPrice + item.laborAmount;
|
let price = item.sellingPrice + item.kitPrice + item.laborAmount;
|
||||||
const packageLineItem = {
|
const packageLineItem = {
|
||||||
|
|
@ -220,11 +237,11 @@ export default {
|
||||||
return this.damage.isRepair;
|
return this.damage.isRepair;
|
||||||
},
|
},
|
||||||
vaps() {
|
vaps() {
|
||||||
const vaps = this.orderLineItems?.vaps;
|
const vaps = this.storeLineItems?.vaps;
|
||||||
return vaps?.length > 0 ? vaps : [];
|
return vaps?.length > 0 ? vaps : [];
|
||||||
},
|
},
|
||||||
supportingItems() {
|
supportingItems() {
|
||||||
const supportingItems = this.orderLineItems?.supportingItems;
|
const supportingItems = this.storeLineItems?.supportingItems;
|
||||||
return supportingItems?.length > 0 ? supportingItems : [];
|
return supportingItems?.length > 0 ? supportingItems : [];
|
||||||
},
|
},
|
||||||
recycleLabel() {
|
recycleLabel() {
|
||||||
|
|
@ -248,6 +265,7 @@ export default {
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
textBlock,
|
textBlock,
|
||||||
|
textLink,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -102,7 +102,7 @@ export default {
|
||||||
},
|
},
|
||||||
show() {
|
show() {
|
||||||
this.isActive = true;
|
this.isActive = true;
|
||||||
this.scrollToPageTop();
|
window.scrollTo({ top: 0, left: 0, behavior: "smooth" });
|
||||||
},
|
},
|
||||||
hide() {
|
hide() {
|
||||||
var self = this;
|
var self = this;
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-md-center">
|
<div class="row justify-content-md-center">
|
||||||
<div class="col-md-6 col-xl-4">
|
<div class="col-md-6">
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
:displayGenericVehicleImage="false" />
|
:displayGenericVehicleImage="false" />
|
||||||
|
|
@ -23,7 +23,10 @@
|
||||||
:manualHeadline="alertFewMoreQuestionsHeader"
|
:manualHeadline="alertFewMoreQuestionsHeader"
|
||||||
:manualCopy="alertFewMoreQuestionsCopy"
|
:manualCopy="alertFewMoreQuestionsCopy"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-md-center">
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
<div v-for="(questionsDatum, i) in questionsData" :key="questionsDatum.key">
|
<div v-for="(questionsDatum, i) in questionsData" :key="questionsDatum.key">
|
||||||
<questionChain
|
<questionChain
|
||||||
ref="questionChain"
|
ref="questionChain"
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,49 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="page-container-grouped-styles position-relative">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<div class="page-container-grouped-styles position-relative">
|
||||||
<div>{{ workOrderNumber }}</div>
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
<div>
|
<div>
|
||||||
<div class="container-fluid pb-2">
|
<div class="container-fluid pb-2">
|
||||||
<div class="row justify-content-md-center">
|
<div class="row justify-content-md-center">
|
||||||
<div class="col-md-6 col-xl-4">
|
<div class="col-md-6 col-xl-4">
|
||||||
<div class="header-container">
|
<div class="header-container">
|
||||||
<img :src="ScheduleConfirmationImage" />
|
<img :src="ScheduleConfirmationImage" />
|
||||||
<span v-html="ScheduleConfirmationText"></span>
|
<span v-html="ScheduleConfirmationText"></span>
|
||||||
</div>
|
|
||||||
<div class="main">
|
|
||||||
<div>
|
|
||||||
<vehicleBanner
|
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
|
||||||
:displayGenericVehicleImage="false" />
|
|
||||||
</div>
|
</div>
|
||||||
<div class="scheduleText">
|
|
||||||
<p>{{ this.getScheduleDate() }}</p>
|
|
||||||
<p>{{ this.getScheduleTime() }}</p>
|
|
||||||
</div>
|
|
||||||
<addToCalendar></addToCalendar>
|
|
||||||
<div
|
<div
|
||||||
class="appoinmenttext"
|
class="appoinmenttext"
|
||||||
v-html="this.getAppointmentWordingText()"></div>
|
v-html="this.getAppointmentWordingText()"></div>
|
||||||
|
|
||||||
|
<div class="main">
|
||||||
|
<div>
|
||||||
|
<vehicleBanner
|
||||||
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
|
:displayGenericVehicleImage="false" />
|
||||||
|
</div>
|
||||||
|
<div class="scheduleText">
|
||||||
|
<p>{{ this.ScheduleDateFormatted }}</p>
|
||||||
|
<p>{{ this.ScheduleTimeFormatted }}</p>
|
||||||
|
</div>
|
||||||
|
<addToCalendar></addToCalendar>
|
||||||
|
|
||||||
|
<div
|
||||||
|
class="appoinmenttext"
|
||||||
|
v-html="this.AppointmentWordingText"></div>
|
||||||
|
</div>
|
||||||
|
<div class="emailtext" v-html="this.ConfirmationEmailText"></div>
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
isBackButtonHidden="true"
|
||||||
|
@ForwardClicked="forwardButtonAction"
|
||||||
|
:buttonSize="true" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="emailtext" v-html="this.getConfirmationEmailText()"></div>
|
|
||||||
<navbar
|
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
|
||||||
ref="navbar"
|
|
||||||
isBackButtonHidden="true"
|
|
||||||
@ForwardClicked="forwardButtonAction"
|
|
||||||
:buttonSize="true" />
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
|
|
@ -49,6 +56,7 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { applicationConfig } from "@/constants/application-config.js";
|
import { applicationConfig } from "@/constants/application-config.js";
|
||||||
|
import { Form } from "vee-validate";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
|
@ -85,7 +93,10 @@ export default {
|
||||||
return this.getCmsContent("ScheduleConfirmationWidget", "Image");
|
return this.getCmsContent("ScheduleConfirmationWidget", "Image");
|
||||||
},
|
},
|
||||||
ConfirmationEmailText() {
|
ConfirmationEmailText() {
|
||||||
return this.getCmsContent("ConfirmationEmailWidget", "BodyText");
|
return this.getCmsContent("ConfirmationEmailWidget", "BodyText")
|
||||||
|
.replaceAll("{custom:MY_ACCOUNT_URL}", applicationConfig.MY_ACCOUNT)
|
||||||
|
.replaceAll("<", "<")
|
||||||
|
.replaceAll(">", ">");
|
||||||
},
|
},
|
||||||
ScheduleDate() {
|
ScheduleDate() {
|
||||||
return store.getters.order.schedule.date;
|
return store.getters.order.schedule.date;
|
||||||
|
|
@ -135,17 +146,50 @@ export default {
|
||||||
ProviderZipCode() {
|
ProviderZipCode() {
|
||||||
return store.getters.order.serviceLocation.provider.address.zipCode;
|
return store.getters.order.serviceLocation.provider.address.zipCode;
|
||||||
},
|
},
|
||||||
Year() {
|
AppointmentWordingText() {
|
||||||
return store.getters.order.vehicle.year;
|
if (this.AppointmentType == AppointmentTypeStrings.MOBILE) {
|
||||||
|
return this.MobileWordingText.replaceAll(
|
||||||
|
"{custom:ADDRESS}",
|
||||||
|
this.ServiceLocationFullAddress
|
||||||
|
);
|
||||||
|
} else if (this.AppointmentType == AppointmentTypeStrings.DROP_OFF) {
|
||||||
|
return this.DropOffWordingText.replaceAll(
|
||||||
|
"{custom:ADDRESS}",
|
||||||
|
this.ProviderFullAddress
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return this.InShopWordingText.replaceAll(
|
||||||
|
"{custom:ADDRESS}",
|
||||||
|
this.ProviderFullAddress
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Make() {
|
ServiceLocationFullAddress() {
|
||||||
return store.getters.order.vehicle.make;
|
return `${this.ServiceLocationAddress2 ? this.ServiceLocationAddress2 + "," : ""} ${
|
||||||
|
this.ServiceLocationAddress
|
||||||
|
},<br/> ${this.ServiceLocationCity}, ${this.ServiceLocationState} ${
|
||||||
|
this.ServiceLocationZipCode
|
||||||
|
}`;
|
||||||
},
|
},
|
||||||
Model() {
|
ProviderFullAddress() {
|
||||||
return store.getters.order.vehicle.model;
|
return `${this.ProviderAddress},<br/> ${this.ProviderCity}, ${this.ProviderState} ${this.ProviderZipCode}`;
|
||||||
},
|
},
|
||||||
Email() {
|
ScheduleDateFormatted() {
|
||||||
return store.getters.order.customer.emailAddress;
|
const scheduleDate = new Date(this.ScheduleDate);
|
||||||
|
return `${getFullDayName(scheduleDate)}, ${getFullMonthName(
|
||||||
|
scheduleDate
|
||||||
|
)} ${scheduleDate.getDate()}`;
|
||||||
|
},
|
||||||
|
ScheduleTimeFormatted() {
|
||||||
|
if (this.AppointmentType == AppointmentTypeStrings.MOBILE) {
|
||||||
|
return `Between ${get12HourTimeMobileFormat(
|
||||||
|
this.ScheduleStartTime
|
||||||
|
)} - ${get12HourTimeMobileFormat(this.ScheduleEndTime)}`;
|
||||||
|
} else if (this.AppointmentType == AppointmentTypeStrings.DROP_OFF) {
|
||||||
|
return `Drop off before 9:30 AM`;
|
||||||
|
} else {
|
||||||
|
return `at ${get12HourTimeFormat(this.ScheduleStartTime)}`;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -186,50 +230,10 @@ export default {
|
||||||
forwardButtonAction() {
|
forwardButtonAction() {
|
||||||
window.location.assign("//www.safelite.com/");
|
window.location.assign("//www.safelite.com/");
|
||||||
},
|
},
|
||||||
getScheduleDate() {
|
|
||||||
const scheduleDate = new Date(this.ScheduleDate);
|
|
||||||
return `${getFullDayName(scheduleDate)}, ${getFullMonthName(
|
|
||||||
scheduleDate
|
|
||||||
)} ${scheduleDate.getDate()}`;
|
|
||||||
},
|
|
||||||
getScheduleTime() {
|
|
||||||
if (this.AppointmentType == AppointmentTypeStrings.MOBILE) {
|
|
||||||
return `Between ${get12HourTimeMobileFormat(
|
|
||||||
this.ScheduleStartTime
|
|
||||||
)} - ${get12HourTimeMobileFormat(this.ScheduleEndTime)}`;
|
|
||||||
} else if (this.AppointmentType == AppointmentTypeStrings.DROP_OFF) {
|
|
||||||
return `Drop off before 9:30 AM`;
|
|
||||||
} else {
|
|
||||||
return `at ${get12HourTimeFormat(this.ScheduleStartTime)}`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
getAppointmentWordingText() {
|
|
||||||
const ymm = `${this.Year} ${this.Make} ${this.Model}`;
|
|
||||||
if (this.AppointmentType == AppointmentTypeStrings.MOBILE) {
|
|
||||||
const address = `${
|
|
||||||
this.ServiceLocationAddress2 ? this.ServiceLocationAddress2 + "," : ""
|
|
||||||
} ${this.ServiceLocationAddress},<br/> ${this.ServiceLocationCity}, ${
|
|
||||||
this.ServiceLocationState
|
|
||||||
} ${this.ServiceLocationZipCode}`;
|
|
||||||
return this.MobileWordingText.replace("#ADDRESS", address).replace("#YMM", ymm);
|
|
||||||
} else if (this.AppointmentType == AppointmentTypeStrings.DROP_OFF) {
|
|
||||||
const address = `${this.ProviderAddress},<br/> ${this.ProviderCity}, ${this.ProviderState} ${this.ProviderZipCode}`;
|
|
||||||
return this.DropOffWordingText.replace("#ADDRESS", address).replace("#YMM", ymm);
|
|
||||||
} else {
|
|
||||||
const address = `${this.ProviderAddress},<br/> ${this.ProviderCity}, ${this.ProviderState} ${this.ProviderZipCode}`;
|
|
||||||
return this.InShopWordingText.replace("#ADDRESS", address).replace("#YMM", ymm);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
getConfirmationEmailText() {
|
|
||||||
return this.ConfirmationEmailText.replace("#EMAIL", this.Email)
|
|
||||||
.replace("#MY_ACCOUNT_URL", applicationConfig.MY_ACCOUNT)
|
|
||||||
.replace(/</g, "<")
|
|
||||||
.replace(/>/g, ">");
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
|
Form,
|
||||||
navbar,
|
navbar,
|
||||||
vehicleBanner,
|
vehicleBanner,
|
||||||
addToCalendar,
|
addToCalendar,
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row justify-content-center">
|
||||||
<div class="col">
|
<div class="col-md-6">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
|
||||||
|
import paymentMethodListButton from "@/layouts/payment-method/payment-method-question/payment-method-list-button/payment-method-list-button";
|
||||||
|
|
||||||
|
const testConstants = {
|
||||||
|
images: {
|
||||||
|
A: "imageA",
|
||||||
|
B: "imageB",
|
||||||
|
NONE: null,
|
||||||
|
},
|
||||||
|
names: {
|
||||||
|
A: "nameA",
|
||||||
|
B: "nameB",
|
||||||
|
},
|
||||||
|
content: {
|
||||||
|
withInline: "Button text with {custom:inlineImage} inline.",
|
||||||
|
noInline: "Button text with no inline",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let cmsContent;
|
||||||
|
|
||||||
|
describe("Payment Method Question", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cmsContent = {};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("Side image", () => {
|
||||||
|
it("Renders side image if image is present and not inline", () => {
|
||||||
|
// Arrange
|
||||||
|
const props = generateDefaultProps();
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
propsData: props,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const showSideImage = wrapper.vm.shouldDisplaySideImage;
|
||||||
|
|
||||||
|
expect(showSideImage).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Does not render side image if no image is present", () => {
|
||||||
|
// Arrange
|
||||||
|
let props = generateDefaultProps();
|
||||||
|
|
||||||
|
props.buttonImage = testConstants.images.NONE;
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
propsData: props,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const showSideImage = wrapper.vm.shouldDisplaySideImage;
|
||||||
|
|
||||||
|
expect(showSideImage).toBe(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Does not render side image if inline", () => {
|
||||||
|
// Arrange
|
||||||
|
let props = generateDefaultProps();
|
||||||
|
|
||||||
|
props.buttonLabel = testConstants.content.withInline;
|
||||||
|
props.altText = testConstants.content.withInline;
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
propsData: props,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const showSideImage = wrapper.vm.shouldDisplaySideImage;
|
||||||
|
|
||||||
|
expect(showSideImage).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function generateDefaultProps() {
|
||||||
|
return {
|
||||||
|
buttonLabel: testConstants.noInline,
|
||||||
|
altText: testConstants.noInline,
|
||||||
|
groupName: "payment-method",
|
||||||
|
value: testConstants.names.A,
|
||||||
|
buttonImage: testConstants.images.A,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupMocks(customMountOptions) {
|
||||||
|
const mountOptions = getMountOptions(customMountOptions);
|
||||||
|
|
||||||
|
const mockMixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
|
||||||
|
return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mountOptions.global.mixins = [mockMixin];
|
||||||
|
|
||||||
|
const wrapper = shallowMount(paymentMethodListButton, mountOptions);
|
||||||
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,123 @@
|
||||||
|
<template>
|
||||||
|
<baseInputButton
|
||||||
|
v-bind="$props"
|
||||||
|
buttonWrapperClasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2"
|
||||||
|
v-model="selectedValue">
|
||||||
|
<div class="button-content list-button-content d-flex flex-row py-3 px-4">
|
||||||
|
<img
|
||||||
|
v-if="shouldDisplaySideImage"
|
||||||
|
:id="buttonImageId"
|
||||||
|
class="ms-auto order-3"
|
||||||
|
: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>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import baseInputButton from "@/digital-components/base-input-button/base-input-button";
|
||||||
|
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
|
||||||
|
import { splitCopyOnCMSPlaceHolder } from "@/helpers/cms-content-helper";
|
||||||
|
|
||||||
|
const INLINE_IMAGE_TOKEN = "custom:inlineImage";
|
||||||
|
|
||||||
|
function isInlineImageToken(token) {
|
||||||
|
return token.includes(INLINE_IMAGE_TOKEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getInlineAltText(token) {
|
||||||
|
let innerTokens = token.split(",");
|
||||||
|
|
||||||
|
return innerTokens[1] ?? "";
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "payment-method-list-button",
|
||||||
|
mixins: [inputButtonWrapperMixin],
|
||||||
|
components: {
|
||||||
|
baseInputButton,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
isInlineImageToken,
|
||||||
|
getInlineAltText,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
tokens() {
|
||||||
|
return splitCopyOnCMSPlaceHolder(this.buttonLabel ?? "");
|
||||||
|
},
|
||||||
|
hasImage() {
|
||||||
|
return !!this.buttonImage;
|
||||||
|
},
|
||||||
|
shouldDisplaySideImage() {
|
||||||
|
return this.hasImage && this.tokens.every((token) => !isInlineImageToken(token));
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.list-button {
|
||||||
|
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 {
|
||||||
|
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;
|
||||||
|
position: relative;
|
||||||
|
background: $white;
|
||||||
|
transition: all 150ms linear;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
border: 1px solid $gray-500;
|
||||||
|
width: 100%;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
span {
|
||||||
|
&.small {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: $gray-550;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -0,0 +1,130 @@
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
|
||||||
|
import paymentMethodQuestion from "@/layouts/payment-method/payment-method-question/payment-method-question";
|
||||||
|
|
||||||
|
const testConstants = {
|
||||||
|
cms: {
|
||||||
|
question: {
|
||||||
|
text: "Choose a payment option",
|
||||||
|
},
|
||||||
|
answers: {
|
||||||
|
optionA: {
|
||||||
|
name: "NameA",
|
||||||
|
text: "TextA",
|
||||||
|
subText: "SubTextA",
|
||||||
|
imageId: "idA",
|
||||||
|
image: "imageA",
|
||||||
|
subWidget: "subWidgetA",
|
||||||
|
},
|
||||||
|
optionB: {
|
||||||
|
name: "NameB",
|
||||||
|
text: "TextB",
|
||||||
|
subText: "SubTextB",
|
||||||
|
imageId: "idB",
|
||||||
|
image: "imageB",
|
||||||
|
subWidget: "subWidgetB",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let cmsContent;
|
||||||
|
|
||||||
|
describe("Payment Method Question", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
cmsContent = {
|
||||||
|
PaymentMethodWidget: {
|
||||||
|
QuestionText: testConstants.cms.question,
|
||||||
|
Answers: [
|
||||||
|
{
|
||||||
|
Name: testConstants.cms.answers.optionA.name,
|
||||||
|
Text: testConstants.cms.answers.optionA.text,
|
||||||
|
SubText: testConstants.cms.answers.optionA.subText,
|
||||||
|
ImageId: testConstants.cms.answers.optionA.imageId,
|
||||||
|
AnswerImageUrl: testConstants.cms.answers.optionA.image,
|
||||||
|
SubWidgetName: testConstants.cms.answers.optionA.subWidget,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: testConstants.cms.answers.optionB.name,
|
||||||
|
Text: testConstants.cms.answers.optionB.text,
|
||||||
|
SubText: testConstants.cms.answers.optionB.subText,
|
||||||
|
ImageId: testConstants.cms.answers.optionB.imageId,
|
||||||
|
AnswerImageUrl: testConstants.cms.answers.optionB.image,
|
||||||
|
SubWidgetName: testConstants.cms.answers.optionB.subWidget,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should map cms content correctly", () => {
|
||||||
|
// Arrange
|
||||||
|
const props = generateDefaultProps();
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
propsData: props,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const mappedContent = wrapper.vm.paymentMethodAnswerData;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mappedContent).toEqual([
|
||||||
|
{
|
||||||
|
buttonLabel: testConstants.cms.answers.optionA.text,
|
||||||
|
altText: testConstants.cms.answers.optionA.text,
|
||||||
|
groupName: "payment-method",
|
||||||
|
value: testConstants.cms.answers.optionA.name,
|
||||||
|
buttonImage: testConstants.cms.answers.optionA.image,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
buttonLabel: testConstants.cms.answers.optionB.text,
|
||||||
|
altText: testConstants.cms.answers.optionB.text,
|
||||||
|
groupName: "payment-method",
|
||||||
|
value: testConstants.cms.answers.optionB.name,
|
||||||
|
buttonImage: testConstants.cms.answers.optionB.image,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Handles null cms content gracefully", () => {
|
||||||
|
// Arrange
|
||||||
|
cmsContent = {};
|
||||||
|
const props = generateDefaultProps();
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
propsData: props,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const mappedContent = wrapper.vm.paymentMethodAnswerData;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(mappedContent).toEqual([]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function generateDefaultProps() {
|
||||||
|
return {
|
||||||
|
modelValue: "modelValue",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupMocks(customMountOptions) {
|
||||||
|
const mountOptions = getMountOptions(customMountOptions);
|
||||||
|
|
||||||
|
const mockMixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
|
||||||
|
return cmsContent?.[widgetName]?.[cmsFieldName] ?? "";
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mountOptions.global.mixins = [mockMixin];
|
||||||
|
|
||||||
|
const wrapper = shallowMount(paymentMethodQuestion, mountOptions);
|
||||||
|
wrapper.vm.setCmsContent = jest.fn();
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
<template>
|
||||||
|
<div class="payment-method-question">
|
||||||
|
<buttonQuestion
|
||||||
|
groupName="payment-method"
|
||||||
|
buttonTypeString="payment-method-list-button"
|
||||||
|
:buttonTypeObject="paymentMethodListButton"
|
||||||
|
isWide
|
||||||
|
:questionText="paymentMethodQuestionText"
|
||||||
|
:answers="paymentMethodAnswerData"
|
||||||
|
isRequired
|
||||||
|
v-model="selectedMethod"
|
||||||
|
textPosition="text-start" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
|
import paymentMethodListButton from "./payment-method-list-button/payment-method-list-button";
|
||||||
|
import { paymentMethods, paymentTimes } from "@/constants/payment-method-constants";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "payment-method-question",
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
paymentMethodListButton: paymentMethodListButton,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
modelValue: String,
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getAnswersNullSafe(widgetName) {
|
||||||
|
const rawData = this.getCmsContent(widgetName, "Answers");
|
||||||
|
|
||||||
|
if (!rawData) {
|
||||||
|
return [];
|
||||||
|
} else {
|
||||||
|
return rawData;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
selectedMethod: {
|
||||||
|
get: function () {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set: function (selectedMethod) {
|
||||||
|
this.$emit("update:modelValue", selectedMethod);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
paymentMethodQuestionText() {
|
||||||
|
return this.getCmsContent("PaymentMethodWidget", "QuestionText");
|
||||||
|
},
|
||||||
|
paymentMethodAnswerData() {
|
||||||
|
const cmsData = this.getAnswersNullSafe("PaymentMethodWidget");
|
||||||
|
|
||||||
|
return cmsData.map((answer) => {
|
||||||
|
return {
|
||||||
|
buttonLabel: answer.Text,
|
||||||
|
altText: answer.Text,
|
||||||
|
groupName: "payment-method",
|
||||||
|
value: answer.Name,
|
||||||
|
buttonImage: answer.AnswerImageUrl,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
buttonQuestion,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.payment-method-question {
|
||||||
|
.question-text span {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -5,6 +5,7 @@ import customerDetails from "@/layouts/payment-method/payment-method.vue";
|
||||||
import { shallowMount } from "@vue/test-utils";
|
import { shallowMount } from "@vue/test-utils";
|
||||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
|
|
||||||
// Mock our module for promises.
|
// Mock our module for promises.
|
||||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
|
|
@ -15,6 +16,8 @@ jest.mock("@/helpers/heritage-integration/order-helper.js", () => ({
|
||||||
submitWorkOrder: jest.fn(),
|
submitWorkOrder: jest.fn(),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
let piaDisabledFlag = false;
|
||||||
|
|
||||||
describe("payment-method.vue", () => {
|
describe("payment-method.vue", () => {
|
||||||
describe("navigation", () => {
|
describe("navigation", () => {
|
||||||
test("if the back button is clicked, navigate back", async () => {
|
test("if the back button is clicked, navigate back", async () => {
|
||||||
|
|
@ -52,19 +55,37 @@ function setupMocks() {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const wrapper = shallowMount(
|
const mountOptions = getMountOptions({
|
||||||
customerDetails,
|
router: {
|
||||||
getMountOptions({
|
navigate: jest.fn(),
|
||||||
router: {
|
navigateWithSaving: jest.fn(),
|
||||||
navigate: jest.fn(),
|
navigateWithoutSaving: jest.fn(),
|
||||||
navigateWithSaving: jest.fn(),
|
},
|
||||||
navigateWithoutSaving: jest.fn(),
|
store: {
|
||||||
},
|
getters: store.getters,
|
||||||
store: {
|
},
|
||||||
getters: store.getters,
|
});
|
||||||
},
|
|
||||||
})
|
const mockMixin = {
|
||||||
);
|
methods: {
|
||||||
|
getSettingValue: jest.fn((settingName) => {
|
||||||
|
if (!piaDisabledFlag) {
|
||||||
|
if (settingName === experimentSettings.PIA_EXPERIENCE) {
|
||||||
|
return "PIA Optional";
|
||||||
|
}
|
||||||
|
if (settingName === experimentSettings.SUBMIT_ORDER_ENABLE_PIA) {
|
||||||
|
return "true";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "false";
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
mountOptions.global.mixins = [mockMixin];
|
||||||
|
|
||||||
|
const wrapper = shallowMount(customerDetails, mountOptions);
|
||||||
|
|
||||||
return { wrapper };
|
return { wrapper };
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,10 @@
|
||||||
|
|
||||||
<cart
|
<cart
|
||||||
:damage="damageInfo"
|
:damage="damageInfo"
|
||||||
:orderLineItems="orderLineItems"
|
:storeLineItems="storeLineItems"
|
||||||
:availableLineItems="cartItems"
|
:availableLineItems="cartItems"
|
||||||
servicePackageOptionsCmsName="ServicePackageTitle" />
|
servicePackageOptionsCmsName="ServicePackageTitle"
|
||||||
|
@cart-remove="cartRemove" />
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<alert
|
<alert
|
||||||
|
|
@ -32,42 +33,18 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<add-vaps-modal-buttons
|
<add-vaps-modal-buttons
|
||||||
:cart="cartItems"
|
:cartItems="cartItems"
|
||||||
:wiperItems="availableWipers"
|
:wiperItems="availableWipers"
|
||||||
:rainDefenseItem="availableRainDefense"
|
:rainDefenseItem="availableRainDefense"
|
||||||
vapsTilesCmsName="VapsProductTiles" />
|
vapsTilesCmsName="VapsProductTiles" />
|
||||||
|
|
||||||
<div>
|
<paymentMethodQuestion
|
||||||
<button v-on:click="ccdPayment">
|
v-if="!isPiaDisabled"
|
||||||
<img
|
v-model="paymentMethodInternalModel" />
|
||||||
src="data:image/png;base64,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"
|
|
||||||
alt="We accept Visa" />
|
|
||||||
</button>
|
|
||||||
<button v-on:click="ccdPayment">
|
|
||||||
<img
|
|
||||||
src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAdCAYAAADoxT9SAAAAAXNSR0IArs4c6QAACeVJREFUWAnNWOlvXFcV/923zMyb8Sz2zNhO7MQ4aUziJM5aO6UkzcIiRKpAIUgEgYQoCRKrhADxL/AFqSCkqiDxgUoRpCBV0NIGsOmXkIY0G06Mkjh2HDteYs+MPZ7lrfzuc8ZxkxnblfjQO3rL3HvPPed3tnvuE3jYenq+GysWi0nADVT6PqxPEVI9x9OLqUhhqq/vtyUpp5C31tbjRiIRO6xp4jnLc9Ps9GT/h7UJRXgKxJBr441r15SrwMu2BKJu2/uNE6qjvAQhEvBWj0ESC873hIROOj5XS+3TcvbC/NXTLSrX5+n0w1W/pWk4Lzr2nEwFXeefqqJ1eq6zOK/WixRAo9BBuDCokjgsRDwHJaEgiwAKiooyVFhVQEnaoOr6VzRgIRGwoSsecqbGS0fJVlByVDgSnbwkwXKNPF3XeSccDD+vRVw94sHdshIIuS55otErocuZxQ4niw1ugaK7FNuDQ642r2ERxhUthstqAuMiBMfXnEBQc/BUtICdqTx2NeawJmJCE540IhxXIG8puDFTh39NxHEjE0GGwDi8PBjPleP7FKWgia7uF9sVWwx6y7qUgOHZ2G1n8Wl7Ap3unK8syUc2isNf5d8C71sE9Fe9Cee0JGJhF0daH+CzbQ+QDptLvLei8ke0pqPg3EQCbw4ncXU6CterzFngVe0eDkWTWrWBpX0uRYzShb5kjeBT9hSoYzqTsnSK/y7BLG0dXgFtpSF8JF1E+3YLzzRn6TKKr/2l8xbeH9FKV/tEyzR2JOfwmxst6L1XD5t0K7UVgYTo/5+zxnCUlpCtGohqTCxpI0XgcGwaSZPgSxRmFYld2qbsKqgPWTjVeQ8W3a53tGFFN1sWqvT7Z226hD3OSBB+HFQTulqfqSpQ6gXCOQeFAcCeoojLcnv/KjJuokEbX98yhvZokfG3PHHNUQmi2S3hBWuc7uQuiYD3M6z2T2G8ZWJB6F2AvpOG4FPQGp65dLbUvbxqNwmmNVzC5zdMIqzZ8Pi/VqsJRFpgDzNTKzOTXeFHAZdPCgtsZKZKlspwr9AV3+N1ie5ywYN9288ynMQFZRD7gVxZvLqI0rWeWzuNj8bzzIDV58jeqjFCdkhQfTuYpfS1ayCiUZg3b0Otr4fW3AhzcAheiZWBzJ2PNUEXKEVVhNpc6NwzFpOhlNeg7NSKYhjQUhsgNB32/ZtwrTwHq+mUG4OqIZZsxtOtFq5NS8me5ClFqEbtx0MDgWwuzaDuq19G+qc/ghIxkDhxHOmf/BBaIgERNqDEoqwLVIhgEKrso4ChZ7oR7doGpUjJRZRsI/AKZGPpwGwIMEOIdB9H/OiPET3ybaiNbXS7KJRQhPNZeOhBKAGDryoULQitYR0ih0+hZyN5MFJqtaoWkZOjzFZxz0Kwazu0da0IbulE3dHPwMsXoK5tQvxrJ6DFY8ic/gOMbZ0w9j2N/NlexL5wDF6xiMzvAojs6/Gtlnv199CeaoexaxetMg5jzzHMvvFz2LkxKmUtYruOcVe0MX/hDIIbu+knQZTvXESofS89YjP1kUYqMM+KgJWDNEqVVhWINF7MKVHLcSh0K2dyEvGvHIdqhFG4MQCWnvQRB0b3XrimifDBj6N8bQDW5BS0xjQKve8g9Z1TMEfHYNA61sgIQgSrb9wAz5qBPT6IUv/fIeg2WiTJpWyENh+AW5olkB7YD4ZppTACbV1UXAZuIQNRzCEWjGG+4OvmCShVXUvOcmz6eHMzPLqOPT4JY2snNZiFPTKG0NbNUBtScB2Hwo7CujmIQEszGa+HM5PF7Jtvc5y5X1GYdh8wBkzotOr0S7+CM52DV85xjNEUjkNfv9OPFc8qMfZV1k4e5vpegZ5qQ+Hi6yjfvQQnM0aQc4y3muJWjxEZlzkSKQxsj8K7hSJKl68BJZMWKCP+xRdg3rkDN8vdenoGmVdPQzBG6g4dpFD07boIQdoovnsRudN/hDnwXyh0Q2d8Ag61rjVtQmDzfuhtexDedZRgbzM1EwjBoEyBbZMWYUKIN9G9umFn7sIsm8hZWrX84ltHbWrZXS9c8X3/38ObTL0BLvbsugRD1UZ56C59dohnLgfFcxegppPUeAIOgSgM9MjHevieQ763D4H16+Dm88xG9xE5coBBHEB5cBB6OoV8Xy/U5DjjbS9CHQdg3f8P1LoGqKEY3LlJWGPX4doWzNvnmUDqYHQegtw6rOv/wMBQFm+N0kOqZC1dC/6satEo40kWiSfVSXxSZFBmiSGYaoXBSiuThVaf8LOVZ7IQCejMXtT2DH1/JoNgcxPy7NeaCoh1NLMvy+AvLVipkIPW6jH26iloBE5ukqk4Rm70ASrJIwhpUbcwy3UjzIzMirSUYhfx8tU0ztxslontiVazaJRz57gVv1fSsZ+uIO0p3c2bY9XLmJFB7Te5j8iNgkENxoMcM++NUosswZMC5vBt0qr+mJMrEgT7gzxD5Ge41rSfYt25h2tJTcvlylyZa3nmvB8XKmNpqhzApSkqi/w0X5IF9kvvVbOWnCDPGJf1egw4CWx1Z/06SwavbIJHsppN11nSUKBbHspxHZoupSNNkDRrJTEv7hHy4TcJdGmrDFD1iqzXeCh5aySNO7NhX6alU5e+15RIAsnSKq8F1qC5XEI99xRpldU3gVw0gOZ2ugvxCxaQSpBS1tgHHl9X4hEs6a9PR/CX4TRMJh9d1Cau4nGPltTJVZ70zugtKFBzNPijwRXfPERHTcz9my6WV6CFK6pekXAhM9ESI6wEfj3QioliYFkQcsWaFqmwk1nirNbIiQ6etybQAKbG1eChP896Ov4mUmhRbew3szBYe0k4tcgrULk94U4+glf6W3DlQZ1/JK7IU+vpA6m1sCSSVnAp1J/1NbilRHlKnMROVsUGraXxzLwg2MJRV65j049MUvWrUR51G3EZCRgDDq5kozjWPoXWaAkBhbS+NiqikwcrYZMHqll+iOgbrcfbd1MYng/REstJR4YPh7WgF7DLjllmHAdrkVTO4/1qDMOKgQ43STA5bHTnmaYdP5PIDw9lut+QMPjxIY7rBD3H7CVjrWyrOHsvxeo1hu08wu5Jz6IlUkZAWohYLJ7TZ/nxoZ8fH87z48PQnOGDWgmEVAOTNtMq0/XOgz9IONm5P/Fz0AEWPfJDybJNjkt3k09pkRg3zDruOUVaIsezrCUjm03OqOjb7+CN1Yc/Iu8GD0pxngArn4PytETlQ4OgFR6nlTRLmxzngcB0Pfe1ZCJwUv4Xu3e/eMj2xC/5Zw33BZWb30p4FteUE6Xryf3ksUS6OKfai0/Hm3yqJJeCfJBGqDzZOO8qnvO9TZvmBxfpd+z4ZocrrL2MCibK1QP5IMz/X3OpaeJ3R4HIuUuXfuHvqP8D/8z6CVVrJhwAAAAASUVORK5CYII="
|
|
||||||
alt="Mastercard" />
|
|
||||||
</button>
|
|
||||||
<button v-on:click="ccdPayment">
|
|
||||||
<img
|
|
||||||
src="data:image/png;base64,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"
|
|
||||||
alt="American Express" />
|
|
||||||
</button>
|
|
||||||
<button v-on:click="ccdPayment">
|
|
||||||
<img
|
|
||||||
src="data:image/png;base64,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"
|
|
||||||
alt="and Discover" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
<button v-on:click="paypal">
|
|
||||||
<img
|
|
||||||
src="https://www.paypalobjects.com/webstatic/en_US/i/buttons/PP_logo_h_100x26.png"
|
|
||||||
alt="PayPal" />
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<navbar
|
<navbar
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
:isBackButtonHidden="shouldHideBackButton"
|
:isBackButtonHidden="shouldHideBackButton"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
|
|
@ -83,6 +60,7 @@
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
import paymentMethodQuestion from "@/layouts/payment-method/payment-method-question/payment-method-question";
|
||||||
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
import cart from "@/fmg-components/cart/cart";
|
import cart from "@/fmg-components/cart/cart";
|
||||||
import addVapsModalButtons from "@/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons";
|
import addVapsModalButtons from "@/fmg-components/add-vaps-modal-buttons/add-vaps-modal-buttons";
|
||||||
|
|
@ -94,7 +72,11 @@ import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
import { paymentMethods } from "@/constants/payment-method-constants";
|
||||||
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
|
|
||||||
import { Form } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
|
import { AppointmentTypeStrings } from "@/constants/schedule-constants";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "paymentMethod",
|
name: "paymentMethod",
|
||||||
|
|
@ -154,15 +136,20 @@ export default {
|
||||||
"payment-method",
|
"payment-method",
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
const storeLineItems = store.getters.lineItems;
|
||||||
|
const cartItems = [
|
||||||
|
...clonedGlassParts,
|
||||||
|
...storeLineItems.supportingItems,
|
||||||
|
...storeLineItems.vaps,
|
||||||
|
];
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next((vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
vm.pricedGlassParts = clonedGlassParts;
|
|
||||||
vm.supportingItems = resultMap.supportingItems;
|
|
||||||
vm.availableLineItems = pricingResults;
|
vm.availableLineItems = pricingResults;
|
||||||
vm.availableWipers = resultMap.wipers;
|
vm.availableWipers = resultMap.wipers;
|
||||||
vm.availableRainDefense = resultMap.rainDefense;
|
vm.availableRainDefense = resultMap.rainDefense;
|
||||||
|
vm.cartItems = cartItems;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -174,11 +161,61 @@ export default {
|
||||||
supportingItems: null,
|
supportingItems: null,
|
||||||
pricedGlassParts: null,
|
pricedGlassParts: null,
|
||||||
displayPaypalAlert: this.getPaypalAlert(),
|
displayPaypalAlert: this.getPaypalAlert(),
|
||||||
|
paymentMethodInternalModel: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
return true;
|
// Line Items
|
||||||
|
const packageReqs = !!store.getters.order.lineItems.supportingItems;
|
||||||
|
|
||||||
|
// Service Location
|
||||||
|
const serviceLocation = store.getters.order.serviceLocation;
|
||||||
|
const mobileReqs = !!(
|
||||||
|
serviceLocation.address &&
|
||||||
|
serviceLocation.city &&
|
||||||
|
serviceLocation.state &&
|
||||||
|
serviceLocation.zipCode
|
||||||
|
);
|
||||||
|
|
||||||
|
const providerLocation = serviceLocation.provider.address;
|
||||||
|
const dropOffInshopReqs = !!(
|
||||||
|
providerLocation.streetAddress &&
|
||||||
|
providerLocation.city &&
|
||||||
|
providerLocation.state &&
|
||||||
|
providerLocation.zipCode
|
||||||
|
);
|
||||||
|
|
||||||
|
const isMobile = serviceLocation.appointmentType === AppointmentTypeStrings.MOBILE;
|
||||||
|
|
||||||
|
const serviceLocationReqs =
|
||||||
|
(isMobile && mobileReqs) || (!isMobile && dropOffInshopReqs);
|
||||||
|
|
||||||
|
// Insurance
|
||||||
|
const isInsuranceSet = store.getters.order.payment.isInsurance !== null;
|
||||||
|
|
||||||
|
// Schedule
|
||||||
|
const schedule = store.getters.order.schedule;
|
||||||
|
const scheduleReqs = !!(
|
||||||
|
schedule.date &&
|
||||||
|
schedule.startTime &&
|
||||||
|
(!isMobile || schedule.endTime) &&
|
||||||
|
schedule.jobMaxMinutes &&
|
||||||
|
schedule.jobMinMinutes
|
||||||
|
);
|
||||||
|
|
||||||
|
// Customer
|
||||||
|
const customer = store.getters.order.customer;
|
||||||
|
const customerReqs = !!(
|
||||||
|
customer.firstName &&
|
||||||
|
customer.lastName &&
|
||||||
|
customer.phoneNumber &&
|
||||||
|
customer.emailAddress
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
packageReqs && serviceLocationReqs && isInsuranceSet && scheduleReqs && customerReqs
|
||||||
|
);
|
||||||
},
|
},
|
||||||
getPaypalAlert() {
|
getPaypalAlert() {
|
||||||
return store.getters.order.payment.piaErrorCode ? true : false;
|
return store.getters.order.payment.piaErrorCode ? true : false;
|
||||||
|
|
@ -186,6 +223,22 @@ export default {
|
||||||
vapsItemsSelectedAction(vapsItemsSelected) {
|
vapsItemsSelectedAction(vapsItemsSelected) {
|
||||||
this.cartItems = vapsItemsSelected;
|
this.cartItems = vapsItemsSelected;
|
||||||
},
|
},
|
||||||
|
// TODO (as part of CSR-1384) enable adding to the cart
|
||||||
|
// vapsItemsSelectedAction(vapsItemsSelected) {
|
||||||
|
// this.cartItems = vapsItemsSelected;
|
||||||
|
// },
|
||||||
|
cartRemove(item) {
|
||||||
|
const matchedIndices = [];
|
||||||
|
this.cartItems.forEach((cartItem, i) => {
|
||||||
|
if (cartItem.partType === item.partType) {
|
||||||
|
console.log("adding this to matchedIndices: ", i);
|
||||||
|
matchedIndices.push(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.cartItems = this.cartItems.filter((cartItem, index) => {
|
||||||
|
return cartItem.partType !== item.partType;
|
||||||
|
});
|
||||||
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
|
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
|
@ -200,22 +253,29 @@ export default {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
async ccdPayment() {
|
async ccdPayment() {
|
||||||
//leaving site, clear any save session promises that we will not be able to resolve when we return
|
this.piaSetup("cc");
|
||||||
this.$refs.loadingModal.showModal();
|
|
||||||
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
|
|
||||||
await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
|
||||||
await this.dispatchStoreAction(storeActions.SAVE_PAY_NOW_TYPE, "cc", false);
|
|
||||||
this.$router.navigateWithoutSaving(
|
|
||||||
this.navigationScenarios.CLICKED_PAY_NOW,
|
|
||||||
this.$route
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
async paypal() {
|
async paypal() {
|
||||||
//leaving site, clear any save session promises that we will not be able to resolve when we return
|
this.piaSetup("pp");
|
||||||
|
},
|
||||||
|
async afterpay() {
|
||||||
|
this.piaSetup("ap");
|
||||||
|
},
|
||||||
|
async piaSetup(payNowType) {
|
||||||
this.$refs.loadingModal.showModal();
|
this.$refs.loadingModal.showModal();
|
||||||
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
|
|
||||||
|
//leaving site, clear any save session promises that we will not be able to resolve when we return
|
||||||
await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
||||||
await this.dispatchStoreAction(storeActions.SAVE_PAY_NOW_TYPE, "pp", false);
|
await this.dispatchStoreAction(storeActions.SAVE_PAY_NOW_TYPE, payNowType, false);
|
||||||
|
|
||||||
|
// make sure pia error codes are reset, and get a pia work order in delete status
|
||||||
|
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, null, false);
|
||||||
|
this.dispatchStoreAction(storeActions.SAVE_PIA_WORK_ORDER, true);
|
||||||
|
|
||||||
|
if (!store.getters.order.workOrderNumber) {
|
||||||
|
await submitWorkOrder({ pageNameToLog: "payment-method" });
|
||||||
|
}
|
||||||
|
|
||||||
this.$router.navigateWithoutSaving(
|
this.$router.navigateWithoutSaving(
|
||||||
this.navigationScenarios.CLICKED_PAY_NOW,
|
this.navigationScenarios.CLICKED_PAY_NOW,
|
||||||
this.$route
|
this.$route
|
||||||
|
|
@ -226,9 +286,42 @@ export default {
|
||||||
damageInfo() {
|
damageInfo() {
|
||||||
return this.$store.getters.damage;
|
return this.$store.getters.damage;
|
||||||
},
|
},
|
||||||
orderLineItems() {
|
storeLineItems() {
|
||||||
|
// console.log("storeLineItems, aka lineItems from store: ", this.$store.getters.lineItems)
|
||||||
return this.$store.getters.lineItems;
|
return this.$store.getters.lineItems;
|
||||||
},
|
},
|
||||||
|
customCtaCopy() {
|
||||||
|
switch (this.paymentMethod) {
|
||||||
|
case paymentMethods.CREDIT_CARD:
|
||||||
|
return "Continue to checkout";
|
||||||
|
case paymentMethods.PAYPAL:
|
||||||
|
return "Continue to Paypal";
|
||||||
|
case paymentMethods.AFTERPAY:
|
||||||
|
return "Continue to Afterpay";
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
isPiaDisabled() {
|
||||||
|
const piaExperience =
|
||||||
|
this.getSettingValue(experimentSettings.PIA_EXPERIENCE) === "PIA Optional";
|
||||||
|
const enablePIA =
|
||||||
|
this.getSettingValue(experimentSettings.SUBMIT_ORDER_ENABLE_PIA) === "true";
|
||||||
|
|
||||||
|
return !(piaExperience && enablePIA);
|
||||||
|
},
|
||||||
|
paymentMethod() {
|
||||||
|
if (this.isPiaDisabled) {
|
||||||
|
return paymentMethods.LATER;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.paymentMethodInternalModel;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
customCtaCopy(newValue) {
|
||||||
|
this.$refs.navbar.updateButtonText(newValue);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
|
|
@ -239,6 +332,7 @@ export default {
|
||||||
cart,
|
cart,
|
||||||
alert,
|
alert,
|
||||||
addVapsModalButtons,
|
addVapsModalButtons,
|
||||||
|
paymentMethodQuestion,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="confirm" ref="confirm" @click="forwardButtonAction"></div>
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
||||||
|
<loadingModal notFullScreen ref="loadingModal" />
|
||||||
|
</Form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -8,17 +10,20 @@ import { queryStrings } from "@/constants/query-strings";
|
||||||
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
import { getQuerystringParameter } from "@/helpers/querystring-helper";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
|
import loadingModal from "@/fmg-components/loading-modal/loading-modal.vue";
|
||||||
|
import { Form } from "vee-validate";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "payment-pia-return",
|
name: "payment-pia-return",
|
||||||
async mounted() {
|
async mounted() {
|
||||||
|
this.$refs.loadingModal.showModal();
|
||||||
const piaError = getQuerystringParameter(queryStrings.ERROR);
|
const piaError = getQuerystringParameter(queryStrings.ERROR);
|
||||||
const token = getQuerystringParameter(queryStrings.TOKEN);
|
const token = getQuerystringParameter(queryStrings.TOKEN);
|
||||||
const payerId = getQuerystringParameter(queryStrings.PAYERID);
|
const payerId = getQuerystringParameter(queryStrings.PAYERID);
|
||||||
|
|
||||||
if (piaError) {
|
if (piaError) {
|
||||||
baseMixin.methods.dispatchStoreAction(
|
baseMixin.methods.dispatchStoreAction(
|
||||||
storeActions.SAVE_PAYPAL_ERROR_CODE,
|
storeActions.SAVE_PIA_ERROR_CODE,
|
||||||
piaError,
|
piaError,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
@ -26,7 +31,7 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
if (token && payerId) {
|
if (token && payerId) {
|
||||||
baseMixin.methods.dispatchStoreAction(
|
baseMixin.methods.dispatchStoreAction(
|
||||||
storeActions.SAVE_PAYPAL_ERROR_CODE,
|
storeActions.SAVE_PIA_ERROR_CODE,
|
||||||
null,
|
null,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
@ -35,11 +40,18 @@ export default {
|
||||||
true,
|
true,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Final work order submit after returning from PIA.
|
||||||
|
await this.dispatchStoreAction(storeActions.RESET_SAVE_SESSION_PROMISE);
|
||||||
await submitWorkOrder({ pageNameToLog: "payment-pia-return" });
|
await submitWorkOrder({ pageNameToLog: "payment-pia-return" });
|
||||||
this.$refs.confirm.click();
|
this.$refs.loadingModal.isModalVisible = false;
|
||||||
|
this.$router.navigateWithoutSaving(
|
||||||
|
this.navigationScenarios.PIA_SUCCESS,
|
||||||
|
this.$route
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
baseMixin.methods.dispatchStoreAction(
|
baseMixin.methods.dispatchStoreAction(
|
||||||
storeActions.SAVE_PAYPAL_ERROR_CODE,
|
storeActions.SAVE_PIA_ERROR_CODE,
|
||||||
piaError,
|
piaError,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
@ -55,7 +67,10 @@ export default {
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_SUCCESS, this.$route);
|
this.$router.navigateWithoutSaving(this.navigationScenarios.PIA_SUCCESS, this.$route);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {},
|
components: {
|
||||||
|
loadingModal,
|
||||||
|
Form,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
<hr class="mt-0" />
|
<hr class="mt-0" />
|
||||||
<div id="card-container">
|
<div id="card-container">
|
||||||
<iframe
|
<iframe
|
||||||
|
ref="paymentFrame"
|
||||||
class="hop-iframe payment-iframe"
|
class="hop-iframe payment-iframe"
|
||||||
name="card-frame"
|
name="card-frame"
|
||||||
id="card-frame"
|
id="card-frame"
|
||||||
|
|
@ -32,7 +33,7 @@
|
||||||
<form
|
<form
|
||||||
ref="myForm"
|
ref="myForm"
|
||||||
id="card-data"
|
id="card-data"
|
||||||
:target="isPaypal ? '_top' : 'card-frame'"
|
:target="paypalPayment ? '_top' : 'card-frame'"
|
||||||
method="POST"
|
method="POST"
|
||||||
:action="checkoutUrl">
|
:action="checkoutUrl">
|
||||||
<input type="hidden" name="paymentType" :value="paymentType" />
|
<input type="hidden" name="paymentType" :value="paymentType" />
|
||||||
|
|
@ -97,7 +98,7 @@
|
||||||
|
|
||||||
<input type="hidden" name="sgtotalamount" :value="displayAmount" />
|
<input type="hidden" name="sgtotalamount" :value="displayAmount" />
|
||||||
<input type="hidden" name="totalAmountDecimal" :value="totalAmount" />
|
<input type="hidden" name="totalAmountDecimal" :value="totalAmount" />
|
||||||
<input type="hidden" name="lineItems" :value="lineItems" />
|
<input type="hidden" name="lineItems" :value="piaLineItems" />
|
||||||
|
|
||||||
<input type="hidden" name="sgdiscountstrikethruamount" value="" />
|
<input type="hidden" name="sgdiscountstrikethruamount" value="" />
|
||||||
|
|
||||||
|
|
@ -151,7 +152,7 @@
|
||||||
value="https://fixmyglasstest.safelite.com/FixMyGlass/Payment.aspx?error=ccTimeout" />
|
value="https://fixmyglasstest.safelite.com/FixMyGlass/Payment.aspx?error=ccTimeout" />
|
||||||
|
|
||||||
<input type="hidden" name="sgTransactionType" value="authorization" />
|
<input type="hidden" name="sgTransactionType" value="authorization" />
|
||||||
<input type="hidden" name="amount" :value="totalAmount" />
|
<input type="hidden" name="amount" :value="amountDue" />
|
||||||
<input type="hidden" name="ctu" :value="ctu" />
|
<input type="hidden" name="ctu" :value="ctu" />
|
||||||
<input type="hidden" name="orderNumber" :value="workOrderNumber" />
|
<input type="hidden" name="orderNumber" :value="workOrderNumber" />
|
||||||
|
|
||||||
|
|
@ -184,6 +185,8 @@ import store from "@/store";
|
||||||
import { externalUrls } from "@/router/router-constants/externalUrl-values";
|
import { externalUrls } from "@/router/router-constants/externalUrl-values";
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import { applicationConfig } from "@/constants/application-config";
|
||||||
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
|
|
||||||
// Validation
|
// Validation
|
||||||
import { Form } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
|
|
@ -193,8 +196,8 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
checkoutUrl: externalUrls.SAFELITE_HOP,
|
checkoutUrl: externalUrls.SAFELITE_HOP,
|
||||||
payPalSuccessUrl: externalUrls.PAYPAL_SUCCESS_URL,
|
payPalSuccessUrl: applicationConfig.PAYPAL_SUCCESS_URL,
|
||||||
payPalCancelUrl: externalUrls.PAYPAL_CANCEL_URL,
|
payPalCancelUrl: applicationConfig.PAYPAL_CANCEL_URL,
|
||||||
paymentType: this.getPaymentType(),
|
paymentType: this.getPaymentType(),
|
||||||
authToken: "",
|
authToken: "",
|
||||||
authSignature: "",
|
authSignature: "",
|
||||||
|
|
@ -211,19 +214,16 @@ export default {
|
||||||
phoneNumber: store.getters.order.customer.phoneNumber,
|
phoneNumber: store.getters.order.customer.phoneNumber,
|
||||||
ctu: store.getters.order.serviceLocation.zipCodeCtu,
|
ctu: store.getters.order.serviceLocation.zipCodeCtu,
|
||||||
referralCorrelationId: store.getters.order.referralCorrelationId,
|
referralCorrelationId: store.getters.order.referralCorrelationId,
|
||||||
// TODO: replace these
|
workOrderNumber: this.getWOrkOrderNumber(),
|
||||||
workOrderNumber: Math.floor(Math.random() * 90000) + 10000,
|
invoiceNumber: this.getInvoiceNumber(),
|
||||||
invoiceNumber: Math.floor(Math.random() * 90000) + 10000,
|
totalAmount: this.getAmountDue(),
|
||||||
totalAmount: "321.00", // TODO: get from cart?
|
displayAmount: this.getDisplayAmountDue(),
|
||||||
displayAmount: "$321.00", // TODO: get from cart?
|
piaLineItems: this.getPiaLineItems(),
|
||||||
lineItems: "Labor|189.99|1||Repair supplies|7.99|1",
|
|
||||||
sgHeaderline1: this.getHeaderLine1(),
|
sgHeaderline1: this.getHeaderLine1(),
|
||||||
sgHeaderline2: this.getHeaderLine2(),
|
sgHeaderline2: this.getHeaderLine2(),
|
||||||
|
paypalPayment: this.isPaypal(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async mounted() {
|
|
||||||
this.fetchSignatureInfo();
|
|
||||||
},
|
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
// Call APIs
|
// Call APIs
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
|
@ -239,8 +239,9 @@ export default {
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
// Call the "next" function to complete the transition to this page.
|
// Call the "next" function to complete the transition to this page.
|
||||||
next((vm) => {
|
next(async (vm) => {
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
vm.fetchSignatureInfo();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -248,6 +249,25 @@ export default {
|
||||||
// TODO
|
// TODO
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
getWOrkOrderNumber() {
|
||||||
|
if (store.getters.order.workOrderNumber) {
|
||||||
|
var items = store.getters.order.workOrderNumber.split("-");
|
||||||
|
return items[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// no work order, set pia error and return
|
||||||
|
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, "NO WORK ORDER", false);
|
||||||
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
},
|
||||||
|
getInvoiceNumber() {
|
||||||
|
if (store.getters.order.workOrderNumber) {
|
||||||
|
return store.getters.order.workOrderNumber.replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
// no work order, set pia error and return
|
||||||
|
this.dispatchStoreAction(storeActions.SAVE_PIA_ERROR_CODE, "NO WORK ORDER", false);
|
||||||
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
},
|
||||||
getAddress1() {
|
getAddress1() {
|
||||||
return store.getters.order.serviceLocation.address
|
return store.getters.order.serviceLocation.address
|
||||||
? store.getters.order.serviceLocation.address
|
? store.getters.order.serviceLocation.address
|
||||||
|
|
@ -288,6 +308,27 @@ export default {
|
||||||
}
|
}
|
||||||
return "";
|
return "";
|
||||||
},
|
},
|
||||||
|
getPiaLineItems() {
|
||||||
|
const itemsClone = { ...store.getters.order.lineItems };
|
||||||
|
delete itemsClone.serverData;
|
||||||
|
|
||||||
|
var itemsForPia = "";
|
||||||
|
for (var propertyName in itemsClone) {
|
||||||
|
for (var item in itemsClone[propertyName]) {
|
||||||
|
var amount =
|
||||||
|
+itemsClone[propertyName][item].laborAmount +
|
||||||
|
+itemsClone[propertyName][item].sellingPrice;
|
||||||
|
itemsForPia += itemsClone[propertyName][item].partType + "|" + amount + "|1|";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return itemsForPia;
|
||||||
|
},
|
||||||
|
getAmountDue() {
|
||||||
|
return baseMixin.methods.getAmountDue(store.getters.order.lineItems);
|
||||||
|
},
|
||||||
|
getDisplayAmountDue() {
|
||||||
|
return baseMixin.methods.getDisplayAmountDue(store.getters.order.lineItems);
|
||||||
|
},
|
||||||
isPaypal() {
|
isPaypal() {
|
||||||
if (this.getPaymentType() == "pp") {
|
if (this.getPaymentType() == "pp") {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -299,7 +340,9 @@ export default {
|
||||||
},
|
},
|
||||||
forwardButtonAction() {},
|
forwardButtonAction() {},
|
||||||
async fetchSignatureInfo() {
|
async fetchSignatureInfo() {
|
||||||
this.$refs.loadingModal.showModal();
|
if (this.isPaypal()) {
|
||||||
|
this.$refs.loadingModal.showModal();
|
||||||
|
}
|
||||||
const signatureInfo = await this.dispatchStoreAction(storeActions.GET_SIGNATURE);
|
const signatureInfo = await this.dispatchStoreAction(storeActions.GET_SIGNATURE);
|
||||||
this.authToken = signatureInfo.data.token;
|
this.authToken = signatureInfo.data.token;
|
||||||
this.authSignature = signatureInfo.data.signature;
|
this.authSignature = signatureInfo.data.signature;
|
||||||
|
|
@ -307,6 +350,17 @@ export default {
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.myForm.submit();
|
this.$refs.myForm.submit();
|
||||||
|
|
||||||
|
if (this.paymentType == "ap") {
|
||||||
|
const iframe = this.$refs.paymentFrame;
|
||||||
|
if (iframe) {
|
||||||
|
iframe.onload = () => {
|
||||||
|
if (iframe.contentWindow) {
|
||||||
|
iframe.contentWindow.postMessage("afterpay", "*");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,12 @@
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
||||||
<!-- When customer-details is added: v-slot="{ meta }" -->
|
<!-- When customer-details is added: v-slot="{ meta }" -->
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="row">
|
<div class="row justify-content-center">
|
||||||
<div class="col">
|
<div class="col-md-6">
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-md-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-6 col-xl-4">
|
<div class="col-md-6 col-xl-4">
|
||||||
<vehicleBanner
|
<vehicleBanner
|
||||||
cmsWidgetName="VehicleBannerWidget"
|
cmsWidgetName="VehicleBannerWidget"
|
||||||
|
|
@ -177,8 +177,7 @@ export default {
|
||||||
// damageReqs handles checking for damage, even though it is also required for this section.
|
// damageReqs handles checking for damage, even though it is also required for this section.
|
||||||
const packageReqs = !!(
|
const packageReqs = !!(
|
||||||
(damage.isRepair || lineItems.glassParts) &&
|
(damage.isRepair || lineItems.glassParts) &&
|
||||||
lineItems.supportingItems &&
|
lineItems.supportingItems
|
||||||
lineItems.vaps
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Service Location
|
// Service Location
|
||||||
|
|
@ -208,7 +207,7 @@ export default {
|
||||||
const scheduleReqs = !!(
|
const scheduleReqs = !!(
|
||||||
schedule.date &&
|
schedule.date &&
|
||||||
schedule.startTime &&
|
schedule.startTime &&
|
||||||
schedule.endTime &&
|
(!isMobile || schedule.endTime) &&
|
||||||
schedule.jobMaxMinutes &&
|
schedule.jobMaxMinutes &&
|
||||||
schedule.jobMinMinutes
|
schedule.jobMinMinutes
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
:answers="answersToDisplay"
|
:answers="answersToDisplay"
|
||||||
:groupName="groupName"
|
:groupName="groupName"
|
||||||
buttonTypeString="listCard"
|
buttonTypeString="listCard"
|
||||||
v-model="selectedValues"
|
v-model="selectedValue"
|
||||||
:suppressError="suppressError"
|
:suppressError="suppressError"
|
||||||
:validationRules="validationRules"
|
:validationRules="validationRules"
|
||||||
isRequired />
|
isRequired />
|
||||||
|
|
@ -55,7 +55,7 @@ export default {
|
||||||
})
|
})
|
||||||
: [];
|
: [];
|
||||||
},
|
},
|
||||||
selectedValues: {
|
selectedValue: {
|
||||||
get: function () {
|
get: function () {
|
||||||
return this.modelValue;
|
return this.modelValue;
|
||||||
},
|
},
|
||||||
|
|
|
||||||
15
src/layouts/service-location/classes/provider-address.js
Normal file
15
src/layouts/service-location/classes/provider-address.js
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
export class ProviderAddress {
|
||||||
|
constructor(
|
||||||
|
streetAddress = null,
|
||||||
|
city = null,
|
||||||
|
state = null,
|
||||||
|
zipCode = null,
|
||||||
|
zipCodeCtu = null
|
||||||
|
) {
|
||||||
|
this.streetAddress = streetAddress;
|
||||||
|
this.city = city;
|
||||||
|
this.state = state;
|
||||||
|
this.zipCode = zipCode;
|
||||||
|
this.zipCodeCtu = zipCodeCtu;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/layouts/service-location/classes/provider.js
Normal file
8
src/layouts/service-location/classes/provider.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
import { ProviderAddress } from "./provider-address";
|
||||||
|
|
||||||
|
export class Provider {
|
||||||
|
constructor(providerNumber = null, address = null) {
|
||||||
|
this.providerNumber = providerNumber;
|
||||||
|
this.address = address ?? new ProviderAddress();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
import store from "@/store";
|
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from "@/mixins/base-mixin.js";
|
||||||
|
|
||||||
export async function getPricedMobileFeePart(serviceZipCode, pageNameToLog) {
|
export async function getPricedMobileFeePart(serviceZipCode, pageNameToLog) {
|
||||||
|
|
|
||||||
|
|
@ -314,9 +314,10 @@ export default {
|
||||||
margin-top: 0em;
|
margin-top: 0em;
|
||||||
}
|
}
|
||||||
|
|
||||||
#mobileLocationLinkPromptId {
|
.update-mobile-location-text-link {
|
||||||
white-space: pre-line;
|
white-space: pre-line;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-black {
|
.text-black {
|
||||||
color: $black;
|
color: $black;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,10 @@ import { getMountOptions } from "@/helpers/unit-test-helper";
|
||||||
|
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import baseMixin from "@/mixins/base-mixin";
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
import { getServiceabilityDetails } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
import {
|
||||||
|
getServiceabilityDetails,
|
||||||
|
Provider,
|
||||||
|
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||||
|
|
||||||
// Define Mocks
|
// Define Mocks
|
||||||
jest.mock("@/helpers/cms-content-helper", () => ({
|
jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
|
|
@ -16,6 +19,8 @@ jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
}),
|
}),
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
jest.mock("./classes/provider");
|
||||||
|
|
||||||
const mockGetPricedMobileFeePart = (mockServiceZipCode) => {
|
const mockGetPricedMobileFeePart = (mockServiceZipCode) => {
|
||||||
let mobileFeePart = {};
|
let mobileFeePart = {};
|
||||||
|
|
||||||
|
|
@ -397,6 +402,7 @@ describe("service-location.vue", () => {
|
||||||
|
|
||||||
await wrapper.setData({
|
await wrapper.setData({
|
||||||
selectedAppointmentType: "Mobile",
|
selectedAppointmentType: "Mobile",
|
||||||
|
providerData: { mobileProviderNumber: "01820" },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mobileLocationQuestionsComponent = wrapper.findComponent({
|
const mobileLocationQuestionsComponent = wrapper.findComponent({
|
||||||
|
|
@ -448,6 +454,7 @@ describe("service-location.vue", () => {
|
||||||
|
|
||||||
await wrapper.setData({
|
await wrapper.setData({
|
||||||
selectedAppointmentType: "Mobile",
|
selectedAppointmentType: "Mobile",
|
||||||
|
providerData: { mobileProviderNumber: "01820" },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mobileLocationQuestionsComponent = wrapper.findComponent({
|
const mobileLocationQuestionsComponent = wrapper.findComponent({
|
||||||
|
|
@ -511,6 +518,7 @@ describe("service-location.vue", () => {
|
||||||
|
|
||||||
await wrapper.setData({
|
await wrapper.setData({
|
||||||
selectedAppointmentType: "Mobile",
|
selectedAppointmentType: "Mobile",
|
||||||
|
providerData: { mobileProviderNumber: "01820" },
|
||||||
});
|
});
|
||||||
|
|
||||||
const mobileLocationQuestionsComponent = wrapper.findComponent({
|
const mobileLocationQuestionsComponent = wrapper.findComponent({
|
||||||
|
|
|
||||||
|
|
@ -60,7 +60,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-md-center appointment-type">
|
<div class="row justify-content-md-center appointment-type">
|
||||||
<div class="col-md-8">
|
<div class="col-md-6">
|
||||||
<appointmentTypeQuestion
|
<appointmentTypeQuestion
|
||||||
v-model="selectedAppointmentType"
|
v-model="selectedAppointmentType"
|
||||||
v-show="isAppointmentTypeDisplayed"
|
v-show="isAppointmentTypeDisplayed"
|
||||||
|
|
@ -95,6 +95,7 @@
|
||||||
v-model="selectedProvider"
|
v-model="selectedProvider"
|
||||||
:selectedAppointmentType="selectedAppointmentType"
|
:selectedAppointmentType="selectedAppointmentType"
|
||||||
:isDisplayed="isShopQuestionDisplayed"
|
:isDisplayed="isShopQuestionDisplayed"
|
||||||
|
@updated-shop-list="setUpdatedShopList"
|
||||||
cmsWidgetName="ShopQuestionWidget" />
|
cmsWidgetName="ShopQuestionWidget" />
|
||||||
|
|
||||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||||
|
|
@ -135,6 +136,9 @@ import {
|
||||||
getPricedMobileFeePart,
|
getPricedMobileFeePart,
|
||||||
getServiceabilityDetails,
|
getServiceabilityDetails,
|
||||||
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
} from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||||
|
|
||||||
|
import { Provider } from "@/layouts/service-location/classes/provider";
|
||||||
|
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
|
||||||
// Validation
|
// Validation
|
||||||
|
|
@ -176,6 +180,7 @@ export default {
|
||||||
mobileFeePart: null,
|
mobileFeePart: null,
|
||||||
zipContainsMilitaryBase: false,
|
zipContainsMilitaryBase: false,
|
||||||
zipCodeCtu: null,
|
zipCodeCtu: null,
|
||||||
|
providerData: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
@ -229,7 +234,12 @@ export default {
|
||||||
resultMap.serviceabilityDetails,
|
resultMap.serviceabilityDetails,
|
||||||
resultMap.mobileFeePart
|
resultMap.mobileFeePart
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Initialize the Shop Question component
|
||||||
vm.$refs.shopQuestion.initializeComponent(resultMap.shopQuestionInitialData);
|
vm.$refs.shopQuestion.initializeComponent(resultMap.shopQuestionInitialData);
|
||||||
|
|
||||||
|
// Initialize the page level shop data
|
||||||
|
vm.providerData = resultMap.shopQuestionInitialData;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -333,6 +343,9 @@ export default {
|
||||||
displayNoShopsAlert() {
|
displayNoShopsAlert() {
|
||||||
return !this.isServiceableInshop && !this.isServiceableMobile;
|
return !this.isServiceableInshop && !this.isServiceableMobile;
|
||||||
},
|
},
|
||||||
|
recalibrationInformationModal() {
|
||||||
|
return this.$refs.recalibrationInformationModal;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
|
|
@ -403,6 +416,15 @@ export default {
|
||||||
this.isRecalibrationServiceableMobile =
|
this.isRecalibrationServiceableMobile =
|
||||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||||
},
|
},
|
||||||
|
async reloadShopData(zipCode) {
|
||||||
|
await this.$refs.shopQuestion.reloadShopData(zipCode);
|
||||||
|
},
|
||||||
|
setUpdatedShopList(providerData) {
|
||||||
|
this.providerData = providerData;
|
||||||
|
},
|
||||||
|
openRecalibrationInformationModal() {
|
||||||
|
this.recalibrationInformationModal.openModal();
|
||||||
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
this.$router.navigateWithoutSaving(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
},
|
},
|
||||||
|
|
@ -472,11 +494,25 @@ export default {
|
||||||
this.updateAndSaveSupportingItems();
|
this.updateAndSaveSupportingItems();
|
||||||
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||||
},
|
},
|
||||||
openModalAction(modalName) {
|
},
|
||||||
this.$refs[modalName].openModal();
|
watch: {
|
||||||
|
selectedAppointmentType: {
|
||||||
|
handler(newValue) {
|
||||||
|
if (newValue === "Mobile") {
|
||||||
|
this.selectedProvider = new Provider(this.providerData.mobileProviderNumber);
|
||||||
|
} else {
|
||||||
|
this.selectedProvider = new Provider();
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
async reloadShopData() {
|
providerData: {
|
||||||
await this.$refs.shopQuestion.reloadShopData(this.zipCode);
|
handler(newValue) {
|
||||||
|
if (newValue === "Mobile") {
|
||||||
|
this.selectedProvider = new Provider(this.providerData.mobileProviderNumber);
|
||||||
|
} else {
|
||||||
|
this.selectedProvider = new Provider();
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -496,11 +532,17 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.appointment-type {
|
.appointment-type-question {
|
||||||
@include media-breakpoint-up(md) {
|
.button-question {
|
||||||
.col {
|
.col {
|
||||||
flex: 0 0 auto;
|
padding: 0 0.5rem;
|
||||||
width: 33.33333333%;
|
@include media-breakpoint-up(md) {
|
||||||
|
padding: 0 0.75rem;
|
||||||
|
}
|
||||||
|
@include media-breakpoint-up(xl) {
|
||||||
|
width: 33.3333333%;
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,8 @@ import { nextTick } from "vue";
|
||||||
|
|
||||||
import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper";
|
||||||
|
|
||||||
|
import { Provider } from "@/layouts/service-location/classes/provider";
|
||||||
|
|
||||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -136,6 +138,7 @@ export default {
|
||||||
},
|
},
|
||||||
initializeComponent(shopQuestionInitialData) {
|
initializeComponent(shopQuestionInitialData) {
|
||||||
this.shopProviders = shopQuestionInitialData.shopProviders;
|
this.shopProviders = shopQuestionInitialData.shopProviders;
|
||||||
|
this.$emit("updated-shop-list", shopQuestionInitialData);
|
||||||
},
|
},
|
||||||
async getNextShopsFromList(numberToGet = 3) {
|
async getNextShopsFromList(numberToGet = 3) {
|
||||||
const shopIterator = (array, n) => {
|
const shopIterator = (array, n) => {
|
||||||
|
|
@ -206,9 +209,9 @@ export default {
|
||||||
await this.getNextShopsFromList();
|
await this.getNextShopsFromList();
|
||||||
},
|
},
|
||||||
getSelectedProviderObject(providerNumber) {
|
getSelectedProviderObject(providerNumber) {
|
||||||
const provider = this.shopProviders?.find(
|
const provider =
|
||||||
(provider) => provider.providerNumber == providerNumber
|
this.shopProviders?.find((provider) => provider.providerNumber == providerNumber) ??
|
||||||
);
|
new Provider();
|
||||||
|
|
||||||
return provider;
|
return provider;
|
||||||
},
|
},
|
||||||
|
|
@ -222,18 +225,15 @@ export default {
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
selectedAppointmentType: {
|
selectedAppointmentType: {
|
||||||
async handler(newValue) {
|
// Question: Does it matter if this fires when clicking Mobile? Ideally it should not, but it doesn't seem to effect anything
|
||||||
|
// What we DON'T want to do here is create a dependency by checking if the selectedAppointmentType is Mobile as that has
|
||||||
|
// nothing to do with this component. We could mitigate this by showing / hiding this component with v-if but that messes
|
||||||
|
// up the component initialization on page load.
|
||||||
|
async handler() {
|
||||||
this.resetAnswers();
|
this.resetAnswers();
|
||||||
|
|
||||||
await nextTick();
|
await nextTick();
|
||||||
|
this.getNextShopsFromList();
|
||||||
this.selectedProviderNumber = null;
|
|
||||||
|
|
||||||
await nextTick();
|
|
||||||
|
|
||||||
if (newValue !== "Mobile") {
|
|
||||||
this.getNextShopsFromList();
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
shopProviders: {
|
shopProviders: {
|
||||||
|
|
|
||||||
|
|
@ -24,13 +24,16 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-md-center">
|
<div class="row justify-content-md-center">
|
||||||
<div class="col-md-8 col-xl-6">
|
<div class="col-md-6">
|
||||||
<damageLocationQuestion
|
<damageLocationQuestion
|
||||||
ref="damageLocation"
|
ref="damageLocation"
|
||||||
cmsWidgetName="DamageLocationQuestion"
|
cmsWidgetName="DamageLocationQuestion"
|
||||||
v-model="selectedDamageLocations"
|
v-model="selectedDamageLocations"
|
||||||
groupName="DamageLocationQuestion" />
|
groupName="DamageLocationQuestion" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-md-center">
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
<windshieldOptions
|
<windshieldOptions
|
||||||
class="windshield-options"
|
class="windshield-options"
|
||||||
ref="windshieldOptions"
|
ref="windshieldOptions"
|
||||||
|
|
@ -547,14 +550,10 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.vehicle-damage {
|
.replace-options-question {
|
||||||
.windshield-options {
|
.two-list-card-width {
|
||||||
@include media-breakpoint-up(md) {
|
width: 100%;
|
||||||
.col {
|
flex: 0 auto;
|
||||||
flex: 0 0 auto;
|
|
||||||
width: 33.33333333%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-md-center">
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
||||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||||
<hr v-if="i > 0" />
|
<hr v-if="i > 0" />
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row justify-content-md-center">
|
<div class="row justify-content-center">
|
||||||
<div class="col-md-6 col-xl-4">
|
<div class="col-md-6 col-xl-4">
|
||||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="siteSubHeader" />
|
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="siteSubHeader" />
|
||||||
<vehicleQuestion
|
<vehicleQuestion
|
||||||
|
|
|
||||||
|
|
@ -65,9 +65,6 @@ export default {
|
||||||
},
|
},
|
||||||
async getZipCodeData(zipCode, pageNameToLog = null) {
|
async getZipCodeData(zipCode, pageNameToLog = null) {
|
||||||
const pageName = pageNameToLog ?? this.$options?.name;
|
const pageName = pageNameToLog ?? this.$options?.name;
|
||||||
if (pageName == null) {
|
|
||||||
console.log("Missed a spot.");
|
|
||||||
}
|
|
||||||
|
|
||||||
const serviceZipValidationResponse = await this.dispatchStoreActionWithLogging(
|
const serviceZipValidationResponse = await this.dispatchStoreActionWithLogging(
|
||||||
storeActions.VALIDATE_ZIP,
|
storeActions.VALIDATE_ZIP,
|
||||||
|
|
@ -118,6 +115,27 @@ export default {
|
||||||
getTotalLineItemPrice(lineItem) {
|
getTotalLineItemPrice(lineItem) {
|
||||||
return lineItem.kitPrice + lineItem.laborAmount + lineItem.sellingPrice;
|
return lineItem.kitPrice + lineItem.laborAmount + lineItem.sellingPrice;
|
||||||
},
|
},
|
||||||
|
getDisplayAmountDue(lineItems) {
|
||||||
|
return this.getAmountDue(lineItems).toLocaleString("en-US", {
|
||||||
|
style: "currency",
|
||||||
|
currency: "USD",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getAmountDue(lineItems) {
|
||||||
|
// TODO: verify tax is included in lineitems
|
||||||
|
// Price everything in lineitems except the server data string
|
||||||
|
var amountDue = 0;
|
||||||
|
const itemsClone = { ...lineItems };
|
||||||
|
delete itemsClone.serverData;
|
||||||
|
for (var propertyName in itemsClone) {
|
||||||
|
if (itemsClone[propertyName]) {
|
||||||
|
amountDue += this.getTotalPriceOfAllLineItemsAndChildParts(
|
||||||
|
itemsClone[propertyName]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return amountDue;
|
||||||
|
},
|
||||||
scrollToPageTop() {
|
scrollToPageTop() {
|
||||||
const container = document.getElementsByClassName("page-container-grouped-styles")[0];
|
const container = document.getElementsByClassName("page-container-grouped-styles")[0];
|
||||||
container.scrollTo({ top: 0, left: 0, behavior: "smooth" });
|
container.scrollTo({ top: 0, left: 0, behavior: "smooth" });
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,6 @@
|
||||||
const externalUrls = {
|
const externalUrls = {
|
||||||
HERITAGE_FUNNEL: process.env.VUE_APP_HERITAGE_FUNNEL,
|
HERITAGE_FUNNEL: process.env.VUE_APP_HERITAGE_FUNNEL,
|
||||||
SAFELITE_HOP: process.env.VUE_APP_SAFELITE_HOP,
|
SAFELITE_HOP: process.env.VUE_APP_SAFELITE_HOP,
|
||||||
PAYPAL_SUCCESS_URL: process.env.VUE_APP_PAYPAL_SUCCESS_URL,
|
|
||||||
PAYPAL_CANCEL_URL: process.env.VUE_APP_PAYPAL_CANCEL_URL,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export { externalUrls };
|
export { externalUrls };
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,7 @@ const getDefaultState = () => {
|
||||||
referralCorrelationId: null,
|
referralCorrelationId: null,
|
||||||
eon: null,
|
eon: null,
|
||||||
workOrderNumber: null,
|
workOrderNumber: null,
|
||||||
|
createDeleteStatusWorkOrderForPia: false,
|
||||||
},
|
},
|
||||||
applicationUser: {
|
applicationUser: {
|
||||||
eventBus: [],
|
eventBus: [],
|
||||||
|
|
@ -223,6 +224,9 @@ export const mutations = {
|
||||||
updatePiaErrorCode(state, piaErrorCode) {
|
updatePiaErrorCode(state, piaErrorCode) {
|
||||||
state.order.payment.piaErrorCode = piaErrorCode;
|
state.order.payment.piaErrorCode = piaErrorCode;
|
||||||
},
|
},
|
||||||
|
updatePiaWorkOrder(state, piaWorkOrder) {
|
||||||
|
state.order.createDeleteStatusWorkOrderForPia = piaWorkOrder;
|
||||||
|
},
|
||||||
updateWorkOrderNumber(state, workOrderNumber) {
|
updateWorkOrderNumber(state, workOrderNumber) {
|
||||||
state.order.workOrderNumber = workOrderNumber;
|
state.order.workOrderNumber = workOrderNumber;
|
||||||
},
|
},
|
||||||
|
|
@ -594,7 +598,10 @@ export const getters = {
|
||||||
funnelServiceCity: state.order.serviceLocation.city,
|
funnelServiceCity: state.order.serviceLocation.city,
|
||||||
funnelServiceState: state.order.serviceLocation.state,
|
funnelServiceState: state.order.serviceLocation.state,
|
||||||
funnelServiceZipCode: state.order.serviceLocation.zipCode,
|
funnelServiceZipCode: state.order.serviceLocation.zipCode,
|
||||||
|
funnelServiceZipCodeCtu: state.order.serviceLocation.zipCodeCtu,
|
||||||
|
funnelProviderNumber: state.order.serviceLocation.provider.providerNumber,
|
||||||
funnelParentAccountNumber: state.order.payment.parentAccountNumber,
|
funnelParentAccountNumber: state.order.payment.parentAccountNumber,
|
||||||
|
funnelReferralType: state.order.payment.isInsurance ? "INSURANCE" : "CASH QUOTE",
|
||||||
funnelIsCoverageVerified: state.order.payment.insuranceCoverage.isVerified,
|
funnelIsCoverageVerified: state.order.payment.insuranceCoverage.isVerified,
|
||||||
funnelHasRecalibrationPart: getHasRecalibrationPart(state),
|
funnelHasRecalibrationPart: getHasRecalibrationPart(state),
|
||||||
funnelSelectedMultiGlass: state.order.damage.glassToReplace?.length > 1,
|
funnelSelectedMultiGlass: state.order.damage.glassToReplace?.length > 1,
|
||||||
|
|
@ -1381,6 +1388,7 @@ export const actions = {
|
||||||
? convertGlassPieceToBackEndCompatibleFormat(order.damage.glassToReplace)
|
? convertGlassPieceToBackEndCompatibleFormat(order.damage.glassToReplace)
|
||||||
: [];
|
: [];
|
||||||
var payload = {
|
var payload = {
|
||||||
|
zipCode: order.serviceLocation.provider.zipCode,
|
||||||
providerNumber: providerNumber,
|
providerNumber: providerNumber,
|
||||||
startDate: startDate,
|
startDate: startDate,
|
||||||
endDate: endDate,
|
endDate: endDate,
|
||||||
|
|
@ -1617,6 +1625,7 @@ export const actions = {
|
||||||
referralNumber: order.referralNumber?.toString(),
|
referralNumber: order.referralNumber?.toString(),
|
||||||
referralSequenceNumber: order.referralSequenceNumber,
|
referralSequenceNumber: order.referralSequenceNumber,
|
||||||
eon: order.eon,
|
eon: order.eon,
|
||||||
|
createDeleteStatusWorkOrderForPia: order.createDeleteStatusWorkOrderForPia,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
logApiCall: true,
|
logApiCall: true,
|
||||||
|
|
@ -1693,6 +1702,9 @@ export const actions = {
|
||||||
savePiaErrorCode(context, piaErrorCode) {
|
savePiaErrorCode(context, piaErrorCode) {
|
||||||
context.commit(storeMutations.UPDATE_PIA_ERROR_CODE, piaErrorCode);
|
context.commit(storeMutations.UPDATE_PIA_ERROR_CODE, piaErrorCode);
|
||||||
},
|
},
|
||||||
|
savePiaWorkOrder(context, piaWorkOrder) {
|
||||||
|
context.commit(storeMutations.UPDATE_PIA_WORK_ORDER, piaWorkOrder);
|
||||||
|
},
|
||||||
|
|
||||||
// Business domain actions
|
// Business domain actions
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2934,6 +2934,9 @@ describe("Getters", () => {
|
||||||
funnelSupportingItems: null,
|
funnelSupportingItems: null,
|
||||||
funnelVaps: null,
|
funnelVaps: null,
|
||||||
funnelGlassToReplace: null,
|
funnelGlassToReplace: null,
|
||||||
|
funnelProviderNumber: "1",
|
||||||
|
funnelReferralType: "CASH QUOTE",
|
||||||
|
funnelServiceZipCodeCtu: "11111",
|
||||||
};
|
};
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
|
|
@ -2948,12 +2951,17 @@ describe("Getters", () => {
|
||||||
city: mockStateValues.funnelServiceCity,
|
city: mockStateValues.funnelServiceCity,
|
||||||
state: mockStateValues.funnelServiceState,
|
state: mockStateValues.funnelServiceState,
|
||||||
zipCode: mockStateValues.funnelServiceZipCode,
|
zipCode: mockStateValues.funnelServiceZipCode,
|
||||||
|
zipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
|
provider: {
|
||||||
|
providerNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
mutations.updateParentAcctNumber(storeState, mockStateValues.funnelParentAccountNumber);
|
mutations.updateParentAcctNumber(storeState, mockStateValues.funnelParentAccountNumber);
|
||||||
mutations.updateInsuranceVerifiedStatus(
|
mutations.updateInsuranceVerifiedStatus(
|
||||||
storeState,
|
storeState,
|
||||||
mockStateValues.funnelIsCoverageVerified
|
mockStateValues.funnelIsCoverageVerified
|
||||||
);
|
);
|
||||||
|
mutations.updateIsInsurance(storeState, false);
|
||||||
mutations.updateGlassParts(storeState, mockStateValues.funnelGlassParts);
|
mutations.updateGlassParts(storeState, mockStateValues.funnelGlassParts);
|
||||||
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
||||||
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
||||||
|
|
@ -2981,6 +2989,9 @@ describe("Getters", () => {
|
||||||
funnelSelectedBackGlass: false,
|
funnelSelectedBackGlass: false,
|
||||||
funnelSelectedDriverSideGlass: false,
|
funnelSelectedDriverSideGlass: false,
|
||||||
funnelSelectedPassengerSideGlass: false,
|
funnelSelectedPassengerSideGlass: false,
|
||||||
|
funnelProviderNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
funnelReferralType: mockStateValues.funnelReferralType,
|
||||||
|
funnelServiceZipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -3003,6 +3014,9 @@ describe("Getters", () => {
|
||||||
funnelGlassParts: [],
|
funnelGlassParts: [],
|
||||||
funnelOtherParts: [],
|
funnelOtherParts: [],
|
||||||
funnelGlassToReplace: [],
|
funnelGlassToReplace: [],
|
||||||
|
funnelProviderNumber: "1",
|
||||||
|
funnelReferralType: "CASH QUOTE",
|
||||||
|
funnelServiceZipCodeCtu: "11111",
|
||||||
};
|
};
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
|
|
@ -3017,12 +3031,17 @@ describe("Getters", () => {
|
||||||
city: mockStateValues.funnelServiceCity,
|
city: mockStateValues.funnelServiceCity,
|
||||||
state: mockStateValues.funnelServiceState,
|
state: mockStateValues.funnelServiceState,
|
||||||
zipCode: mockStateValues.funnelServiceZipCode,
|
zipCode: mockStateValues.funnelServiceZipCode,
|
||||||
|
zipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
|
provider: {
|
||||||
|
providerNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
mutations.updateParentAcctNumber(storeState, mockStateValues.funnelParentAccountNumber);
|
mutations.updateParentAcctNumber(storeState, mockStateValues.funnelParentAccountNumber);
|
||||||
mutations.updateInsuranceVerifiedStatus(
|
mutations.updateInsuranceVerifiedStatus(
|
||||||
storeState,
|
storeState,
|
||||||
mockStateValues.funnelIsCoverageVerified
|
mockStateValues.funnelIsCoverageVerified
|
||||||
);
|
);
|
||||||
|
mutations.updateIsInsurance(storeState, false);
|
||||||
mutations.updateGlassParts(storeState, mockStateValues.funnelGlassParts);
|
mutations.updateGlassParts(storeState, mockStateValues.funnelGlassParts);
|
||||||
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
||||||
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
||||||
|
|
@ -3050,6 +3069,9 @@ describe("Getters", () => {
|
||||||
funnelSelectedBackGlass: false,
|
funnelSelectedBackGlass: false,
|
||||||
funnelSelectedDriverSideGlass: false,
|
funnelSelectedDriverSideGlass: false,
|
||||||
funnelSelectedPassengerSideGlass: false,
|
funnelSelectedPassengerSideGlass: false,
|
||||||
|
funnelProviderNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
funnelReferralType: mockStateValues.funnelReferralType,
|
||||||
|
funnelServiceZipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -3085,6 +3107,9 @@ describe("Getters", () => {
|
||||||
glassName: "Single",
|
glassName: "Single",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
funnelProviderNumber: "1",
|
||||||
|
funnelReferralType: "CASH QUOTE",
|
||||||
|
funnelServiceZipCodeCtu: "11111",
|
||||||
};
|
};
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
|
|
@ -3099,9 +3124,14 @@ describe("Getters", () => {
|
||||||
city: mockStateValues.serviceCity,
|
city: mockStateValues.serviceCity,
|
||||||
state: mockStateValues.serviceState,
|
state: mockStateValues.serviceState,
|
||||||
zipCode: mockStateValues.serviceZipCode,
|
zipCode: mockStateValues.serviceZipCode,
|
||||||
|
zipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
|
provider: {
|
||||||
|
providerNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
mutations.updateParentAcctNumber(storeState, mockStateValues.parentAccountNumber);
|
mutations.updateParentAcctNumber(storeState, mockStateValues.parentAccountNumber);
|
||||||
mutations.updateInsuranceVerifiedStatus(storeState, mockStateValues.isCoverageVerified);
|
mutations.updateInsuranceVerifiedStatus(storeState, mockStateValues.isCoverageVerified);
|
||||||
|
mutations.updateIsInsurance(storeState, false);
|
||||||
mutations.updateGlassParts(storeState, mockStateValues.glassParts);
|
mutations.updateGlassParts(storeState, mockStateValues.glassParts);
|
||||||
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
||||||
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
||||||
|
|
@ -3129,6 +3159,9 @@ describe("Getters", () => {
|
||||||
funnelSelectedBackGlass: false,
|
funnelSelectedBackGlass: false,
|
||||||
funnelSelectedDriverSideGlass: false,
|
funnelSelectedDriverSideGlass: false,
|
||||||
funnelSelectedPassengerSideGlass: false,
|
funnelSelectedPassengerSideGlass: false,
|
||||||
|
funnelProviderNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
funnelReferralType: mockStateValues.funnelReferralType,
|
||||||
|
funnelServiceZipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -3190,6 +3223,9 @@ describe("Getters", () => {
|
||||||
glassName: "Quarter",
|
glassName: "Quarter",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
funnelProviderNumber: "1",
|
||||||
|
funnelReferralType: "CASH QUOTE",
|
||||||
|
funnelServiceZipCodeCtu: "11111",
|
||||||
};
|
};
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
|
|
@ -3204,9 +3240,14 @@ describe("Getters", () => {
|
||||||
city: mockStateValues.serviceCity,
|
city: mockStateValues.serviceCity,
|
||||||
state: mockStateValues.serviceState,
|
state: mockStateValues.serviceState,
|
||||||
zipCode: mockStateValues.serviceZipCode,
|
zipCode: mockStateValues.serviceZipCode,
|
||||||
|
zipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
|
provider: {
|
||||||
|
providerNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
mutations.updateParentAcctNumber(storeState, mockStateValues.parentAccountNumber);
|
mutations.updateParentAcctNumber(storeState, mockStateValues.parentAccountNumber);
|
||||||
mutations.updateInsuranceVerifiedStatus(storeState, mockStateValues.isCoverageVerified);
|
mutations.updateInsuranceVerifiedStatus(storeState, mockStateValues.isCoverageVerified);
|
||||||
|
mutations.updateIsInsurance(storeState, false);
|
||||||
mutations.updateGlassParts(storeState, mockStateValues.glassParts);
|
mutations.updateGlassParts(storeState, mockStateValues.glassParts);
|
||||||
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
mutations.updateSupportingItems(storeState, mockStateValues.funnelSupportingItems);
|
||||||
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
mutations.updateVaps(storeState, mockStateValues.funnelVaps);
|
||||||
|
|
@ -3234,6 +3275,9 @@ describe("Getters", () => {
|
||||||
funnelSelectedBackGlass: true,
|
funnelSelectedBackGlass: true,
|
||||||
funnelSelectedDriverSideGlass: true,
|
funnelSelectedDriverSideGlass: true,
|
||||||
funnelSelectedPassengerSideGlass: true,
|
funnelSelectedPassengerSideGlass: true,
|
||||||
|
funnelProviderNumber: mockStateValues.funnelProviderNumber,
|
||||||
|
funnelReferralType: mockStateValues.funnelReferralType,
|
||||||
|
funnelServiceZipCodeCtu: mockStateValues.funnelServiceZipCodeCtu,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,7 @@ body {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: #4d5151;
|
color: #4d5151;
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
max-width: 1400px;
|
|
||||||
padding: 0 1.5rem;
|
padding: 0 1.5rem;
|
||||||
position: relative;
|
|
||||||
.prevent-squish {
|
.prevent-squish {
|
||||||
overflow-x: unset;
|
overflow-x: unset;
|
||||||
}
|
}
|
||||||
|
|
@ -43,9 +41,11 @@ body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Disable scroll of main container when modal is open
|
|
||||||
.modal-open {
|
.modal-open {
|
||||||
.page-container-grouped-styles {
|
.container-fluid {
|
||||||
overflow: hidden;
|
&.page-container-grouped-styles {
|
||||||
|
overflow: hidden;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -188,3 +188,11 @@ $modal-backdrop-opacity: 0;
|
||||||
|
|
||||||
//Disable default !important behavior
|
//Disable default !important behavior
|
||||||
$enable-important-utilities: false;
|
$enable-important-utilities: false;
|
||||||
|
|
||||||
|
//Bootstrap Grid Breakpoints - Use these breakpoints only
|
||||||
|
$grid-breakpoints: (
|
||||||
|
xs: 0,
|
||||||
|
md: 768px,
|
||||||
|
xl: 1200px,
|
||||||
|
xxl: 1440px,
|
||||||
|
);
|
||||||
|
|
|
||||||
|
|
@ -6,8 +6,6 @@ process.env.VUE_APP_MY_ACCOUNT = "https://myaccountdev.safelite.com/";
|
||||||
|
|
||||||
//process.env.VUE_APP_SAFELITE_HOP = "http://localhost:60966/fmgCheckoutEmbedded.aspx";
|
//process.env.VUE_APP_SAFELITE_HOP = "http://localhost:60966/fmgCheckoutEmbedded.aspx";
|
||||||
process.env.VUE_APP_SAFELITE_HOP = "https://sv2-safelitehop-sys.safelite.com/fmgCheckoutEmbedded.aspx";
|
process.env.VUE_APP_SAFELITE_HOP = "https://sv2-safelitehop-sys.safelite.com/fmgCheckoutEmbedded.aspx";
|
||||||
process.env.VUE_APP_PAYPAL_SUCCESS_URL = "http://localhost:8080/fmg/?fmgPage=payment-pia-return&src=concept-funnel";
|
|
||||||
process.env.VUE_APP_PAYPAL_CANCEL_URL = "http://localhost:8080/fmg/?fmgPage=payment-method&src=concept-funnel";
|
|
||||||
|
|
||||||
// GA & GTM
|
// GA & GTM
|
||||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
|
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
|
||||||
|
|
|
||||||
|
|
@ -5,8 +5,6 @@ process.env.VUE_APP_CURRENT_ENVIRONMENT = "__VUE_APP_CURRENT_ENVIRONMENT__";
|
||||||
process.env.VUE_APP_MY_ACCOUNT = "__VUE_APP_MY_ACCOUNT__";
|
process.env.VUE_APP_MY_ACCOUNT = "__VUE_APP_MY_ACCOUNT__";
|
||||||
|
|
||||||
process.env.VUE_APP_SAFELITE_HOP = "__VUE_APP_SAFELITE_HOP__";
|
process.env.VUE_APP_SAFELITE_HOP = "__VUE_APP_SAFELITE_HOP__";
|
||||||
process.env.VUE_APP_PAYPAL_SUCCESS_URL = "__VUE_APP_PAYPAL_SUCCESS_URL__";
|
|
||||||
process.env.VUE_APP_PAYPAL_CANCEL_URL = "__VUE_APP_PAYPAL_CANCEL_URL__";
|
|
||||||
|
|
||||||
// GA & GTM
|
// GA & GTM
|
||||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY = "__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__";
|
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY = "__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__";
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue