Merge branch 'develop' into CASH-191-button-fix-2
This commit is contained in:
commit
e3c3d08fbe
6 changed files with 434 additions and 1 deletions
|
|
@ -34,7 +34,7 @@ module.exports = {
|
|||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||
coverageThreshold: {
|
||||
global: {
|
||||
statements: 75,
|
||||
statements: 74,
|
||||
},
|
||||
},
|
||||
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit
|
||||
|
|
|
|||
|
|
@ -107,6 +107,7 @@ const storeActions = {
|
|||
|
||||
CREATE_SUBMITTED_ORDER: "createSubmittedOrder",
|
||||
RESET_SUBMITTED_ORDER: "resetSubmittedOrder",
|
||||
ADD_DONATION_TO_SUBMITTED_ORDER: "addDonationToSubmittedOrder",
|
||||
RESET_EXTERNAL_PARAMETER_STATE: "resetExternalParameterState",
|
||||
UPDATE_EXTERNAL_PARAMETER_MMS: "updateExternalParameterMMS",
|
||||
|
||||
|
|
|
|||
274
src/experiment-components/donation-block.vue
Normal file
274
src/experiment-components/donation-block.vue
Normal file
|
|
@ -0,0 +1,274 @@
|
|||
<template>
|
||||
<div class="donation-block">
|
||||
<form ref="donationForm" id="donation-form" @submit.prevent="handleDonationAction">
|
||||
<div class="row g-0">
|
||||
<div class="col-12">
|
||||
<p class="headline text-center" v-html="DonationHeadline"></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row-align d-flex px-4">
|
||||
<div>
|
||||
<img class="w-100 mt-1 me-4" :src="LogoImage" />
|
||||
</div>
|
||||
<div>
|
||||
<p class="small subheadline mb-2" v-html="DonationSubHeadline"></p>
|
||||
<p class="caption mb-0" v-html="DonationBodyText"></p>
|
||||
<textLink
|
||||
linkType="newWindowLink"
|
||||
text="Learn more"
|
||||
:href="DonationBodySubText"
|
||||
target="_blank" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="px-4" :class="[showDonationSuccess ? 'hide-donation-block' : 'show-donation-block']">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="donation-slider my-4">
|
||||
<input
|
||||
name="amount"
|
||||
id="one"
|
||||
type="radio"
|
||||
:value="donationValues[0]"
|
||||
checked />
|
||||
<label for="one" class="label">$1</label>
|
||||
<input name="amount" id="three" type="radio" :value="donationValues[1]" />
|
||||
<label for="three" class="label">$3</label>
|
||||
<input name="amount" id="five" type="radio" :value="donationValues[2]" />
|
||||
<label for="five" class="label">$5</label>
|
||||
<div class="indicator-bar"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<button
|
||||
class="btn btn-secondary w-100 mb-2"
|
||||
v-html="DonationAddButtonWidget"></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-4">
|
||||
<div class="col-12">
|
||||
<div
|
||||
v-if="showDonationSuccess"
|
||||
class="d-flex justify-content-center align-items-center btn-success w-100 mb-2"
|
||||
v-html="DonationThanksAlertWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row px-4">
|
||||
<div class="col">
|
||||
<alert
|
||||
v-if="showDonationError"
|
||||
cmsWidgetName="DonationErrorWidget"
|
||||
alertClass="alert-danger" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<p class="my-4 mx-0 text-center caption" v-html="DonationFooterText"></p>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import textLink from "@/ux-components/text-link/text-link";
|
||||
import alert from "@/ux-components/alert/alert";
|
||||
export default {
|
||||
name: "donationBlock",
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
modelValue: String,
|
||||
showDonationSuccess: Boolean,
|
||||
showDonationError: Boolean,
|
||||
donationValues: Array,
|
||||
},
|
||||
computed: {
|
||||
DonationHeadline() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "HeaderText");
|
||||
},
|
||||
DonationSubHeadline() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
|
||||
},
|
||||
DonationBodyText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "BodyText");
|
||||
},
|
||||
DonationBodySubText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "BodyText2");
|
||||
},
|
||||
DonationAddButtonWidget() {
|
||||
return this.getCmsContent("DonationAddButtonWidget", "Text");
|
||||
},
|
||||
DonationThanksAlertWidget() {
|
||||
return this.getCmsContent("DonationThanksAlertWidget", "Text");
|
||||
},
|
||||
DonationFooterText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "FooterText");
|
||||
},
|
||||
LogoImage() {
|
||||
return this.getCmsContent("DonationWidget", "Image");
|
||||
},
|
||||
selectedValue: {
|
||||
get: function () {
|
||||
return this.modelValue?.toString();
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.$emit("update:modelValue", newValue);
|
||||
},
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleDonationAction(submitEvent) {
|
||||
console.log(
|
||||
"running handleDonationAction(), submitEvent.target.elements.amount.value: ",
|
||||
submitEvent.target.elements.amount.value
|
||||
);
|
||||
this.selectedValue = submitEvent.target.elements.amount.value;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
textLink,
|
||||
alert,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.donation-block {
|
||||
padding: 1rem 0;
|
||||
background-color: $gray-100;
|
||||
border-radius: 0;
|
||||
|
||||
.hide-donation-block {
|
||||
max-height: 0;
|
||||
overflow: hidden;
|
||||
margin-top: 1rem;
|
||||
opacity: 0;
|
||||
transition: all 250ms ease-in;
|
||||
}
|
||||
|
||||
.show-donation-block {
|
||||
max-height: 136px;
|
||||
overflow: hidden;
|
||||
margin-top: 0;
|
||||
opacity: 1;
|
||||
transition: all 250ms ease-in;
|
||||
}
|
||||
|
||||
p {
|
||||
&.headline {
|
||||
font-family: AvertaBold;
|
||||
color: $red;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
&.subheadline {
|
||||
font-family: AvertaBold;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(a) {
|
||||
&.new-window-link {
|
||||
color: $blue;
|
||||
font-size: 0.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
width: 5rem;
|
||||
}
|
||||
|
||||
.donation-slider {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
background: $blue-100;
|
||||
border-radius: 3rem;
|
||||
box-shadow: 0px 0px 4px 1px rgba(0, 112, 209, 1) inset;
|
||||
font-size: 0.875rem;
|
||||
.label {
|
||||
position: relative;
|
||||
display: inline-flex;
|
||||
width: 33.3333%;
|
||||
height: 3rem;
|
||||
padding: 0;
|
||||
cursor: pointer;
|
||||
transition: color 200ms ease-out;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: $blue;
|
||||
z-index: 1;
|
||||
}
|
||||
.indicator-bar {
|
||||
width: 33.3333%;
|
||||
height: 3rem;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: -2rem;
|
||||
background: $blue;
|
||||
border-radius: 3rem;
|
||||
box-shadow: 0px 0px 0px 1px rgba(0, 112, 209, 1) inset;
|
||||
transition: transform 750ms cubic-bezier(0.02, 0.94, 0.09, 0.97);
|
||||
transform: translate3d(2rem, 0, 0);
|
||||
}
|
||||
.indicator-bar {
|
||||
background: $blue;
|
||||
}
|
||||
input {
|
||||
&#one:checked {
|
||||
~ .indicator-bar {
|
||||
transform: translateX(2rem);
|
||||
}
|
||||
}
|
||||
&#three:checked {
|
||||
~ .indicator-bar {
|
||||
transform: translateX(calc(100% + 2rem));
|
||||
}
|
||||
}
|
||||
&#five:checked {
|
||||
~ .indicator-bar {
|
||||
transform: translateX(calc(200% + 2rem));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input:checked {
|
||||
+ label {
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
input[type="radio"] {
|
||||
&:not(:checked),
|
||||
&:checked {
|
||||
position: absolute;
|
||||
left: -999999px;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.alert {
|
||||
border: 1px solid $red;
|
||||
}
|
||||
.btn-success {
|
||||
background: $green-100;
|
||||
border: 1px solid $green-400;
|
||||
border-radius: 0.5rem;
|
||||
height: 3rem;
|
||||
padding: 0.5rem;
|
||||
font-weight: 600;
|
||||
&:before {
|
||||
content: "";
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 17 16'%3E%3Cg clip-path='url(%23a)'%3E%3Cpath fill='%230C7E47' d='M8.5 0a8 8 0 1 0 0 16 8 8 0 0 0 0-16Zm3.7 6.171-4.449 4.45a.559.559 0 0 1-.8 0l-2.16-2.16a.563.563 0 0 1 .792-.8l1.76 1.76 4.066-4.042a.563.563 0 1 1 .792.8v-.008Z'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='a'%3E%3Cpath fill='%23fff' d='M.5 0h16v16H.5z'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E");
|
||||
width: 1rem;
|
||||
height: 0.95rem;
|
||||
position: relative;
|
||||
left: -0.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -64,6 +64,19 @@
|
|||
:isItac="isItac"
|
||||
:isNoComp="isNoComp" />
|
||||
|
||||
<div class="mt-3">
|
||||
<donationBlock
|
||||
cmsWidgetName="DonationWidget"
|
||||
v-model="donationAmount"
|
||||
:donationValues="donationValues"
|
||||
:showDonationSuccess="showDonationSuccess"
|
||||
:showDonationError="showDonationError" />
|
||||
</div>
|
||||
|
||||
<!-- <button type="button" @click="addDonation(3)">
|
||||
Add Donation of $3
|
||||
</button> -->
|
||||
|
||||
<hr class="mb-5" />
|
||||
|
||||
<div class="emailtext" v-html="ConfirmationEmailText"></div>
|
||||
|
|
@ -108,6 +121,7 @@ import experimentMixin from "@/mixins/experiment-mixin.js";
|
|||
import { partTypeStrings } from "@/constants/part-type-strings";
|
||||
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
||||
import { containsRecalParts } from "@/helpers/recal-helper.js";
|
||||
import donationBlock from "@/experiment-components/donation-block.vue";
|
||||
|
||||
export default {
|
||||
name: "confirmation",
|
||||
|
|
@ -204,6 +218,11 @@ export default {
|
|||
return hasRecalPriceRemoveExperiment && isRecalibrationOnOrder;
|
||||
};
|
||||
|
||||
const donationItems = lineItemsFromSubmittedOrder.supportingItems?.filter(
|
||||
(item) => item.partNumber === "DONATION"
|
||||
);
|
||||
const donationAmount = donationItems?.length > 0 ? donationItems[0].sellingPrice : 0;
|
||||
|
||||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
|
|
@ -211,6 +230,7 @@ export default {
|
|||
vm.vaps = availableVaps;
|
||||
vm.submittedOrder = submittedOrder;
|
||||
vm.shouldHideRecalibration = shouldHideRecalibration();
|
||||
vm.donationAmount = donationAmount;
|
||||
});
|
||||
},
|
||||
data() {
|
||||
|
|
@ -219,6 +239,9 @@ export default {
|
|||
vaps: [],
|
||||
submittedOrder: null,
|
||||
shouldHideRecalibration: null,
|
||||
donationAmount: 0,
|
||||
showDonationSuccess: null,
|
||||
showDonationError: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -447,6 +470,9 @@ export default {
|
|||
);
|
||||
}
|
||||
},
|
||||
donationValues() {
|
||||
return [1, 3, 5];
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
arePagePrerequisitesValid() {
|
||||
|
|
@ -489,6 +515,56 @@ export default {
|
|||
forwardButtonAction() {
|
||||
window.location.assign(location.protocol + "//" + location.host);
|
||||
},
|
||||
async addDonation(amount, plateTemp) {
|
||||
// try to call API to add donation to order
|
||||
|
||||
// TEMP DUMMY CALL TO SIMULATE SUCCESS OR ERROR FROM API CALL
|
||||
// TO BE REPLACED BY REAL CALL LATER
|
||||
const donationResponse = await this.dispatchStoreActionWithLogging(
|
||||
storeActions.LOOKUP_VIN_BY_PLATE,
|
||||
{ licensePlate: plateTemp, licenseState: "OH" },
|
||||
"test",
|
||||
false
|
||||
).catch((error) => {
|
||||
// this.$refs.navbar.removeLoader();
|
||||
console.error("Error!!! error: ", error);
|
||||
return error;
|
||||
});
|
||||
|
||||
console.log("ran addDonation()... (*fake call*) donationResponse: ", donationResponse);
|
||||
|
||||
if (donationResponse?.status == "200") {
|
||||
this.showDonationSuccess = true;
|
||||
this.showDonationError = false;
|
||||
const donationResponse = await baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.ADD_DONATION_TO_SUBMITTED_ORDER,
|
||||
amount,
|
||||
false
|
||||
);
|
||||
} else {
|
||||
this.showDonationError = true;
|
||||
this.showDonationSuccess = false;
|
||||
const donationResponse = await baseMixin.methods.dispatchStoreAction(
|
||||
storeActions.ADD_DONATION_TO_SUBMITTED_ORDER,
|
||||
0,
|
||||
false
|
||||
);
|
||||
}
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
donationAmount(newValue) {
|
||||
newValue = parseInt(newValue);
|
||||
console.log("WATCHED donationAmount changed: ", newValue);
|
||||
|
||||
// this.addDonation(newValue);
|
||||
// TODO - when backend code is final, then remove the below and restore the line above
|
||||
if (newValue === 5) {
|
||||
this.addDonation(newValue, "FAILING_PLATE"); // throws error
|
||||
} else {
|
||||
this.addDonation(newValue, "2fast"); // should give successful response
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
funnelHeader,
|
||||
|
|
@ -497,6 +573,7 @@ export default {
|
|||
addToCalendar,
|
||||
cart,
|
||||
textBlock,
|
||||
donationBlock,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import { singleWindshieldCarIds } from "@/constants/single-windshield-carids";
|
|||
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper.js";
|
||||
import { deepEqual } from "@/helpers/object-helper";
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
import {
|
||||
AppointmentTypeStrings,
|
||||
PREMIUM_FEE_PART_TYPE,
|
||||
|
|
@ -524,6 +525,7 @@ export const mutations = {
|
|||
},
|
||||
resetExternalParameterQuoteState(state) {
|
||||
externalParameterState.quote.servicePackage = null;
|
||||
externalParameterState.quote.isInsurance = null;
|
||||
saveExternalParameterState(externalParameterState);
|
||||
},
|
||||
resetIsExternalParameter(state) {
|
||||
|
|
@ -3159,6 +3161,42 @@ export const actions = {
|
|||
context.commit(storeMutations.UPDATE_AFFILIATE_COOKIES, affiliateCookies);
|
||||
},
|
||||
|
||||
addDonationToSubmittedOrder(context, donationAmount) {
|
||||
console.log("running addDonationToSubmittedOrder()... donationAmount: ", donationAmount);
|
||||
|
||||
const submittedOrder = deepClone(baseMixin.methods.getSubmittedOrder());
|
||||
|
||||
if (donationAmount > 0) {
|
||||
console.log(
|
||||
"running addDonationToSubmittedOrder()... adding donation to supportingItems in session storage "
|
||||
);
|
||||
submittedOrder.lineItems.supportingItems.push({
|
||||
partNumber: "DONATION",
|
||||
description: null,
|
||||
partType: "DONATION",
|
||||
isInsurable: false,
|
||||
isChildPart: false,
|
||||
laborAmount: 0,
|
||||
sellingPrice: donationAmount,
|
||||
kitPrice: 0,
|
||||
salesTax: null,
|
||||
id: "donation-" + donationAmount,
|
||||
});
|
||||
} else {
|
||||
// filter out all donations
|
||||
console.log(
|
||||
"running addDonationToSubmittedOrder()... removing all donation items in supportingItems in session storage "
|
||||
);
|
||||
|
||||
const nonDonationItems = submittedOrder.lineItems.supportingItems.filter((item) => {
|
||||
return item.partType !== "DONATION";
|
||||
});
|
||||
submittedOrder.lineItems.supportingItems = nonDonationItems;
|
||||
}
|
||||
// set to local storage
|
||||
window.sessionStorage.setItem("submittedOrder", JSON.stringify(submittedOrder));
|
||||
},
|
||||
|
||||
resetSubmittedOrder(context) {
|
||||
// clear from local storage
|
||||
window.sessionStorage.removeItem("submittedOrder");
|
||||
|
|
|
|||
|
|
@ -156,5 +156,48 @@ export default {
|
|||
transition: background 0s 0s ease-in-out;
|
||||
}
|
||||
}
|
||||
&.btn-success {
|
||||
position: relative;
|
||||
background: $green-100;
|
||||
border: 1px solid $green-400;
|
||||
border-radius: $border-radius-lg;
|
||||
color: $black;
|
||||
font-weight: 500;
|
||||
transition: all 150ms linear;
|
||||
height: 3rem;
|
||||
&:hover {
|
||||
color: $black;
|
||||
background: $green-200;
|
||||
}
|
||||
&:focus, // Mouse, touch, stylus focus
|
||||
&:focus-visible {
|
||||
// Keyboard focus for accessibility
|
||||
outline: none;
|
||||
box-shadow:
|
||||
0 0 0 3px $white,
|
||||
0 0 0 5.5px $green-400;
|
||||
color: $black;
|
||||
background: $green-100;
|
||||
}
|
||||
&:disabled {
|
||||
background: transparent;
|
||||
color: $gray-550 !important;
|
||||
font-weight: 400;
|
||||
height: 48px;
|
||||
border: 1px solid $gray-550;
|
||||
border-radius: $border-radius-lg;
|
||||
cursor: pointer;
|
||||
pointer-events: all;
|
||||
}
|
||||
&.has-loader {
|
||||
color: $white;
|
||||
@include blue-gradient;
|
||||
pointer-events: none;
|
||||
}
|
||||
&.delay {
|
||||
// fixes flicker while transitioning between states
|
||||
transition: background 0s 0s ease-in-out;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Reference in a new issue