Merge branch 'develop' into rlsmerge/2025.02.27-to-develop
This commit is contained in:
commit
ea9feb856b
18 changed files with 189 additions and 55 deletions
|
|
@ -22,7 +22,8 @@ resources:
|
||||||
- container: awscli
|
- container: awscli
|
||||||
image: packagerepository.sagaws.net:8082/safelite/awscli2-build:3.9
|
image: packagerepository.sagaws.net:8082/safelite/awscli2-build:3.9
|
||||||
- container: prettier-node
|
- container: prettier-node
|
||||||
image: packagerepository.sagaws.net:8082/safelite/prettier-node-build:18
|
image: ghcr.io/safelite/prettier-node-build:23
|
||||||
|
endpoint: GitHub Docker
|
||||||
repositories:
|
repositories:
|
||||||
- repository: AzureDevOps
|
- repository: AzureDevOps
|
||||||
type: github
|
type: github
|
||||||
|
|
@ -37,15 +38,15 @@ variables:
|
||||||
stages:
|
stages:
|
||||||
# PR's
|
# PR's
|
||||||
- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
|
- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}:
|
||||||
# - stage: TestFormat
|
- stage: TestFormat
|
||||||
# displayName: Test Code Format
|
displayName: Test Code Format
|
||||||
# jobs:
|
jobs:
|
||||||
# - job: checkFormatting
|
- job: checkFormatting
|
||||||
# displayName: Check formatting
|
displayName: Check formatting
|
||||||
# container: prettier-node
|
container: prettier-node
|
||||||
# steps:
|
steps:
|
||||||
# - bash: prettier --check "$(Build.SourcesDirectory)/src/**/*.(js|vue)"
|
- bash: prettier --check "$(Build.SourcesDirectory)/src/**/*.(js|vue)"
|
||||||
# displayName: Run Prettier check
|
displayName: Run Prettier check
|
||||||
|
|
||||||
- stage: TestPr
|
- stage: TestPr
|
||||||
displayName: Run Unit Tests For PullRequest
|
displayName: Run Unit Tests For PullRequest
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ const experimentSettings = {
|
||||||
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold",
|
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_INTERNAL: "NextGen_InternalInsuranceTabDisplayThreshold",
|
||||||
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold",
|
INSURANCE_TAB_TO_DISPLAY_THRESHOLD_EXTERNAL: "NextGen_ExternalInsuranceTabDisplayThreshold",
|
||||||
DISPLAY_MSR: "DisplayMSR",
|
DISPLAY_MSR: "DisplayMSR",
|
||||||
|
DISPLAY_WAITLIST: "DisplayWaitlist2.0",
|
||||||
|
WAITLIST_THRESHOLD_DAYS: "Waitlist_Threshold_Days",
|
||||||
PRICING_BY_DAY: "DisplayPricingByDay",
|
PRICING_BY_DAY: "DisplayPricingByDay",
|
||||||
FOSTER_LOVE: "DisplayFosterLove",
|
FOSTER_LOVE: "DisplayFosterLove",
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ const partNumberStrings = {
|
||||||
// Recalibration
|
// Recalibration
|
||||||
MOBILE_STATIC_RECAL_FEE: "RECAL MOBILE",
|
MOBILE_STATIC_RECAL_FEE: "RECAL MOBILE",
|
||||||
MOBILE_DUAL_RECAL_FEE: "RECAL MOBILEDUAL",
|
MOBILE_DUAL_RECAL_FEE: "RECAL MOBILEDUAL",
|
||||||
|
DONATION: "DONATION",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { partNumberStrings };
|
export { partNumberStrings };
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@ const storeActions = {
|
||||||
SAVE_EMAIL: "saveEmail",
|
SAVE_EMAIL: "saveEmail",
|
||||||
SAVE_PHONE_NUMBER: "savePhoneNumber",
|
SAVE_PHONE_NUMBER: "savePhoneNumber",
|
||||||
SAVE_IS_SMS_OPT_IN: "saveIsSmsOptIn",
|
SAVE_IS_SMS_OPT_IN: "saveIsSmsOptIn",
|
||||||
|
SAVE_WAITLIST_REQUESTED: "saveWaitListRequested",
|
||||||
SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP: "saveRegistrationLicensePlateLookup",
|
SAVE_REGISTRATION_LICENSE_PLATE_LOOKUP: "saveRegistrationLicensePlateLookup",
|
||||||
SAVE_VIN: "saveVin",
|
SAVE_VIN: "saveVin",
|
||||||
SAVE_REGISTRATION_ADDRESS_LOOKUP: "saveRegistrationAddressLookup",
|
SAVE_REGISTRATION_ADDRESS_LOOKUP: "saveRegistrationAddressLookup",
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,7 @@ const storeMutations = {
|
||||||
UPDATE_CUSTOMER_PHONE_NUMBER: "updateCustomerPhoneNumber",
|
UPDATE_CUSTOMER_PHONE_NUMBER: "updateCustomerPhoneNumber",
|
||||||
UPDATE_CUSTOMER_IS_SMS_OPT_IN: "updateCustomerIsSmsOptin",
|
UPDATE_CUSTOMER_IS_SMS_OPT_IN: "updateCustomerIsSmsOptin",
|
||||||
UPDATE_CUSTOMER_DETAILS: "updateCustomerDetails",
|
UPDATE_CUSTOMER_DETAILS: "updateCustomerDetails",
|
||||||
|
UPDATE_CUSTOMER_WAITLIST_REQUESTED: "updateCustomerWaitListRequested",
|
||||||
|
|
||||||
// ORDER MUTATIONS
|
// ORDER MUTATIONS
|
||||||
UPDATE_REFERRAL_NUMBER: "updateReferralNumber",
|
UPDATE_REFERRAL_NUMBER: "updateReferralNumber",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="text-block w-100" :class="[justifyText, typeStyle, fontWeight, marginTopClass]">
|
<div
|
||||||
|
class="text-block w-100"
|
||||||
|
:class="[justifyText, typeStyle, fontWeight, marginTopClass]"
|
||||||
|
:style="{ 'font-weight': fontWeight }">
|
||||||
<span v-for="copy in splitCopyOnCMSPlaceHolder(this.textBlockCopy)" :key="copy">
|
<span v-for="copy in splitCopyOnCMSPlaceHolder(this.textBlockCopy)" :key="copy">
|
||||||
<span v-if="doesCopyContainRouterLink(copy)">
|
<span v-if="doesCopyContainRouterLink(copy)">
|
||||||
<textLink
|
<textLink
|
||||||
|
|
|
||||||
|
|
@ -130,10 +130,6 @@ export default {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleDonationAction(submitEvent) {
|
handleDonationAction(submitEvent) {
|
||||||
console.log(
|
|
||||||
"running handleDonationAction(), submitEvent.target.elements.amount.value: ",
|
|
||||||
submitEvent.target.elements.amount.value
|
|
||||||
);
|
|
||||||
this.selectedValue = submitEvent.target.elements.amount.value;
|
this.selectedValue = submitEvent.target.elements.amount.value;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
<template>
|
<template>
|
||||||
<baseInputButton v-bind="$props" @buttonClicked="handleAnswerChange" v-model="selectedValue">
|
<baseInputButton v-bind="$props" @buttonClicked="handleAnswerChange" v-model="selectedValue">
|
||||||
<div
|
<div
|
||||||
class="package-label"
|
class="package-label pricing-by-day-pkg-lbl"
|
||||||
:class="[
|
:class="[
|
||||||
this.buttonLabelSubCopy ? 'has-subheader' : '',
|
this.buttonLabelSubCopy ? 'has-subheader' : '',
|
||||||
this.isInsuranceSelected ? 'pricing-by-day-pkg-lbl-ins' : 'pricing-by-day-pkg-lbl',
|
|
||||||
!this.additionalButtonData.servicePackageDiscount ? 'adjust-top' : '',
|
!this.additionalButtonData.servicePackageDiscount ? 'adjust-top' : '',
|
||||||
]"
|
]"
|
||||||
for="testradio">
|
for="testradio">
|
||||||
|
|
@ -21,9 +20,7 @@
|
||||||
</div>
|
</div>
|
||||||
<span class="col md-6 service-package-discount-pricing-by-day">
|
<span class="col md-6 service-package-discount-pricing-by-day">
|
||||||
<div>
|
<div>
|
||||||
<span v-if="!isInsuranceSelected" class="caption pricing-by-day">
|
<span class="caption pricing-by-day">as low as</span>
|
||||||
as low as
|
|
||||||
</span>
|
|
||||||
<div
|
<div
|
||||||
class="strikethrough-discount-price"
|
class="strikethrough-discount-price"
|
||||||
v-if="shouldDisplayStrikeThroughPrice"
|
v-if="shouldDisplayStrikeThroughPrice"
|
||||||
|
|
@ -36,9 +33,7 @@
|
||||||
<p class="m-0">
|
<p class="m-0">
|
||||||
<span v-html="this.buttonLabel"></span>
|
<span v-html="this.buttonLabel"></span>
|
||||||
<span class="pricing-info-pricing-by-day">
|
<span class="pricing-info-pricing-by-day">
|
||||||
<span v-if="!isInsuranceSelected" class="caption pricing-by-day">
|
<span class="caption pricing-by-day">as low as</span>
|
||||||
as low as
|
|
||||||
</span>
|
|
||||||
<span
|
<span
|
||||||
class="strikethrough-price"
|
class="strikethrough-price"
|
||||||
v-if="shouldDisplayStrikeThroughPrice"
|
v-if="shouldDisplayStrikeThroughPrice"
|
||||||
|
|
@ -208,7 +203,7 @@ export default {
|
||||||
}
|
}
|
||||||
@include media-breakpoint-up(lg) {
|
@include media-breakpoint-up(lg) {
|
||||||
&:before {
|
&:before {
|
||||||
top: .5rem;
|
top: 0.5rem;
|
||||||
}
|
}
|
||||||
&:after {
|
&:after {
|
||||||
top: 1.4375rem;
|
top: 1.4375rem;
|
||||||
|
|
@ -223,7 +218,7 @@ export default {
|
||||||
|
|
||||||
+ .package-label.pricing-by-day-pkg-lbl-ins {
|
+ .package-label.pricing-by-day-pkg-lbl-ins {
|
||||||
&:before {
|
&:before {
|
||||||
top: .3125rem;
|
top: 0.3125rem;
|
||||||
}
|
}
|
||||||
&:after {
|
&:after {
|
||||||
top: 1.25rem;
|
top: 1.25rem;
|
||||||
|
|
@ -234,7 +229,7 @@ export default {
|
||||||
&:before {
|
&:before {
|
||||||
top: 0.9375rem;
|
top: 0.9375rem;
|
||||||
@include media-breakpoint-up(lg) {
|
@include media-breakpoint-up(lg) {
|
||||||
top: .3125rem;
|
top: 0.3125rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:after {
|
&:after {
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ export default {
|
||||||
transition: background 0s 0s ease-in-out;
|
transition: background 0s 0s ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal.modal-component .modal-dialog .modal-content {
|
.modal.modal-component .modal-dialog .modal-content {
|
||||||
.modal-header {
|
.modal-header {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,19 @@ import { experimentSettings } from "@/constants/experiments";
|
||||||
|
|
||||||
const mockExperimentSettings = experimentSettings;
|
const mockExperimentSettings = experimentSettings;
|
||||||
|
|
||||||
|
jest.mock("@/mixins/experiment-mixin.js", () => ({
|
||||||
|
methods: {
|
||||||
|
getSettingValue(settingName) {
|
||||||
|
if (settingName === mockExperimentSettings.RECAL_PRICE_REMOVE) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
hasSettingEqualTo(settingName, settingValue) {
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
// Mock our module for promises.
|
// Mock our module for promises.
|
||||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
settleAllPromises: jest.fn(),
|
settleAllPromises: jest.fn(),
|
||||||
|
|
@ -572,13 +585,6 @@ function setupMocks({ customMountOptions }) {
|
||||||
getCmsContent: jest.fn().mockImplementation(() => {
|
getCmsContent: jest.fn().mockImplementation(() => {
|
||||||
return wordingText;
|
return wordingText;
|
||||||
}),
|
}),
|
||||||
getSettingValue: jest.fn((settingName) => {
|
|
||||||
if (settingName === experimentSettings.RECAL_PRICE_REMOVE) {
|
|
||||||
return "true";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "false";
|
|
||||||
}),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@
|
||||||
:isItac="isItac"
|
:isItac="isItac"
|
||||||
:isNoComp="isNoComp" />
|
:isNoComp="isNoComp" />
|
||||||
|
|
||||||
<div class="mt-3" v-if="displayFosterLove">
|
<div class="mt-3" v-if="DisplayFosterLove">
|
||||||
<donationBlock
|
<donationBlock
|
||||||
cmsWidgetName="DonationWidget"
|
cmsWidgetName="DonationWidget"
|
||||||
v-model="donationAmount"
|
v-model="donationAmount"
|
||||||
|
|
@ -73,10 +73,6 @@
|
||||||
:showDonationError="showDonationError" />
|
:showDonationError="showDonationError" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- <button type="button" @click="addDonation(3)">
|
|
||||||
Add Donation of $3
|
|
||||||
</button> -->
|
|
||||||
|
|
||||||
<hr class="mb-5" />
|
<hr class="mb-5" />
|
||||||
|
|
||||||
<div class="emailtext" v-html="ConfirmationEmailText"></div>
|
<div class="emailtext" v-html="ConfirmationEmailText"></div>
|
||||||
|
|
@ -122,6 +118,7 @@ import { partTypeStrings } from "@/constants/part-type-strings";
|
||||||
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
import { containsLineItemWithPartType } from "@/helpers/service-package-helper";
|
||||||
import { containsRecalParts } from "@/helpers/recal-helper.js";
|
import { containsRecalParts } from "@/helpers/recal-helper.js";
|
||||||
import donationBlock from "@/experiment-components/donation-block.vue";
|
import donationBlock from "@/experiment-components/donation-block.vue";
|
||||||
|
import { partNumberStrings } from "@/constants/part-number-strings";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "confirmation",
|
name: "confirmation",
|
||||||
|
|
@ -219,7 +216,7 @@ export default {
|
||||||
};
|
};
|
||||||
|
|
||||||
const donationItems = lineItemsFromSubmittedOrder.supportingItems?.filter(
|
const donationItems = lineItemsFromSubmittedOrder.supportingItems?.filter(
|
||||||
(item) => item.partNumber === "DONATION"
|
(item) => item.partNumber === partNumberStrings.DONATION
|
||||||
);
|
);
|
||||||
const donationAmount = donationItems?.length > 0 ? donationItems[0].sellingPrice : 0;
|
const donationAmount = donationItems?.length > 0 ? donationItems[0].sellingPrice : 0;
|
||||||
|
|
||||||
|
|
@ -532,13 +529,9 @@ export default {
|
||||||
"test",
|
"test",
|
||||||
false
|
false
|
||||||
).catch((error) => {
|
).catch((error) => {
|
||||||
// this.$refs.navbar.removeLoader();
|
|
||||||
console.error("Error!!! error: ", error);
|
|
||||||
return error;
|
return error;
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("ran addDonation()... (*fake call*) donationResponse: ", donationResponse);
|
|
||||||
|
|
||||||
if (donationResponse?.status == "200") {
|
if (donationResponse?.status == "200") {
|
||||||
this.showDonationSuccess = true;
|
this.showDonationSuccess = true;
|
||||||
this.showDonationError = false;
|
this.showDonationError = false;
|
||||||
|
|
@ -561,7 +554,6 @@ export default {
|
||||||
watch: {
|
watch: {
|
||||||
donationAmount(newValue) {
|
donationAmount(newValue) {
|
||||||
newValue = parseInt(newValue);
|
newValue = parseInt(newValue);
|
||||||
console.log("WATCHED donationAmount changed: ", newValue);
|
|
||||||
|
|
||||||
// this.addDonation(newValue);
|
// this.addDonation(newValue);
|
||||||
// TODO - when backend code is final, then remove the below and restore the line above
|
// TODO - when backend code is final, then remove the below and restore the line above
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ jest.mock("@/mixins/experiment-mixin.js", () => ({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hasSettingEqualTo(settingName, settingValue) {
|
hasSettingEqualTo(settingName, settingValue) {
|
||||||
return true;
|
return false;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
@ -851,7 +851,7 @@ function setupMocks({ mountOptionsMockData, props = mockProps }) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
mountOptionsMockData = Object.assign(mountOptionsMockDataDefault, mountOptionsMockData);
|
mountOptionsMockData = Object.assign(mountOptionsMockDataDefault, mountOptionsMockData);
|
||||||
const mountOptions = getMountOptions(mountOptionsMockData);
|
const mountOptions = getMountOptions(mountOptionsMockData);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -227,11 +227,9 @@ export default {
|
||||||
methods: {
|
methods: {
|
||||||
processIfStatements,
|
processIfStatements,
|
||||||
hasPricingByDay() {
|
hasPricingByDay() {
|
||||||
return (
|
return experimentMixin.methods.hasSettingEqualTo(
|
||||||
experimentMixin.methods.hasSettingEqualTo(
|
experimentSettings.PRICING_BY_DAY,
|
||||||
experimentSettings.PRICING_BY_DAY,
|
"true"
|
||||||
"true"
|
|
||||||
) && !this.isInsuranceSelected
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
getHeaderTextFromCms(cmsWidgetName) {
|
getHeaderTextFromCms(cmsWidgetName) {
|
||||||
|
|
@ -264,6 +262,10 @@ export default {
|
||||||
servicePackageDiscount,
|
servicePackageDiscount,
|
||||||
})
|
})
|
||||||
).toFixed(2);
|
).toFixed(2);
|
||||||
|
|
||||||
|
if (this.hasPricingByDay()) {
|
||||||
|
return "$" + formattedPriceFloat;
|
||||||
|
}
|
||||||
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
|
return (this.isInsuranceSelected ? "As little as $" : "$") + formattedPriceFloat;
|
||||||
},
|
},
|
||||||
getPackagePrice(packageName, { discountedPrice = false, servicePackageDiscount = false }) {
|
getPackagePrice(packageName, { discountedPrice = false, servicePackageDiscount = false }) {
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,7 @@ describe("schedule.vue...", () => {
|
||||||
days: [],
|
days: [],
|
||||||
};
|
};
|
||||||
wrapper.vm.updateFooterButtonText = jest.fn();
|
wrapper.vm.updateFooterButtonText = jest.fn();
|
||||||
|
wrapper.vm.setDisplayWaitList = jest.fn();
|
||||||
const nextFunction = jest.fn((c) => {
|
const nextFunction = jest.fn((c) => {
|
||||||
c(wrapper.vm);
|
c(wrapper.vm);
|
||||||
});
|
});
|
||||||
|
|
@ -338,6 +339,7 @@ describe("schedule.vue...", () => {
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
expect(wrapper.vm.updateFooterButtonText).toHaveBeenCalled();
|
expect(wrapper.vm.updateFooterButtonText).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.setDisplayWaitList).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,8 @@
|
||||||
customComponentId="timeSlotModalQuestion"
|
customComponentId="timeSlotModalQuestion"
|
||||||
v-model="selectedTimeSlotInfo"
|
v-model="selectedTimeSlotInfo"
|
||||||
cmsWidgetName="TimeSlotModalQuestion"
|
cmsWidgetName="TimeSlotModalQuestion"
|
||||||
|
waitListLabelWidget="WaitListLabelWidget"
|
||||||
|
waitListQuestionWidget="WaitListQuestionWidget"
|
||||||
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
||||||
mobileCmsWidgetName="MobileTimeSlotModal"
|
mobileCmsWidgetName="MobileTimeSlotModal"
|
||||||
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
||||||
|
|
@ -51,6 +53,7 @@
|
||||||
:selectedDate="selectedDate"
|
:selectedDate="selectedDate"
|
||||||
:appointmentType="appointmentType"
|
:appointmentType="appointmentType"
|
||||||
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
||||||
|
:displayWaitList="displayWaitList"
|
||||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||||
:estimatedServiceMinutesMinimum="
|
:estimatedServiceMinutesMinimum="
|
||||||
selectableDatesData.estimatedServiceMinutesMinimum
|
selectableDatesData.estimatedServiceMinutesMinimum
|
||||||
|
|
@ -58,6 +61,7 @@
|
||||||
:estimatedServiceMinutesMaximum="
|
:estimatedServiceMinutesMaximum="
|
||||||
selectableDatesData.estimatedServiceMinutesMaximum
|
selectableDatesData.estimatedServiceMinutesMaximum
|
||||||
"
|
"
|
||||||
|
@waitListRequested-emitted="handleWaitListRequested"
|
||||||
@time-slot-modal-closed="timeSlotModalClosed"
|
@time-slot-modal-closed="timeSlotModalClosed"
|
||||||
validationRules="time-slot-selection-required"
|
validationRules="time-slot-selection-required"
|
||||||
@TimeSlotSelected="forwardButtonAction" />
|
@TimeSlotSelected="forwardButtonAction" />
|
||||||
|
|
@ -217,6 +221,8 @@ export default {
|
||||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||||
selectableDatesData: [],
|
selectableDatesData: [],
|
||||||
mobilePremiumAppointmentFee: null,
|
mobilePremiumAppointmentFee: null,
|
||||||
|
waitListRequested: null,
|
||||||
|
displayWaitList: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
@ -295,6 +301,7 @@ export default {
|
||||||
? resultMap.premiumFeeWithPrice[0]
|
? resultMap.premiumFeeWithPrice[0]
|
||||||
: null;
|
: null;
|
||||||
vm.updateFooterButtonText(vm.selectedTimeSlotInfo);
|
vm.updateFooterButtonText(vm.selectedTimeSlotInfo);
|
||||||
|
vm.setDisplayWaitList();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -469,6 +476,29 @@ export default {
|
||||||
forwardButtonAction() {
|
forwardButtonAction() {
|
||||||
this.updateSupportingItems();
|
this.updateSupportingItems();
|
||||||
|
|
||||||
|
if (this.waitListRequested) {
|
||||||
|
var gaLabel = store.getters.isMobileAppointment
|
||||||
|
? "checked_mobile"
|
||||||
|
: "checked_inshop";
|
||||||
|
|
||||||
|
const currentDate = new Date();
|
||||||
|
const dateString = this.selectableDatesData.days[0].date;
|
||||||
|
const [year, month, day] = dateString.split("-").map(Number);
|
||||||
|
const appointmentDate = new Date(year, month - 1, day);
|
||||||
|
const timeDifference = appointmentDate - currentDate;
|
||||||
|
|
||||||
|
// Convert the time difference from milliseconds to days
|
||||||
|
const daysUntilAppointment = Math.ceil(timeDifference / (1000 * 60 * 60 * 24));
|
||||||
|
|
||||||
|
gaLabel +=
|
||||||
|
"_" +
|
||||||
|
daysUntilAppointment.toString() +
|
||||||
|
"_" +
|
||||||
|
store.getters.order.serviceLocation.zipCode +
|
||||||
|
"_" +
|
||||||
|
store.getters.order.serviceLocation.zipCodeCtu;
|
||||||
|
this.pushEventToGA("waitlist", "add_to_waitlist_check_box_status", gaLabel, true);
|
||||||
|
}
|
||||||
if (this.selectedTimeSlotInfo.timeSlot.jobMinMinutes == null) {
|
if (this.selectedTimeSlotInfo.timeSlot.jobMinMinutes == null) {
|
||||||
this.selectedTimeSlotInfo.timeSlot.jobMinMinutes =
|
this.selectedTimeSlotInfo.timeSlot.jobMinMinutes =
|
||||||
this.selectableDatesData?.estimatedServiceMinutesMinimum?.toString();
|
this.selectableDatesData?.estimatedServiceMinutesMinimum?.toString();
|
||||||
|
|
@ -482,8 +512,44 @@ export default {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.dispatchStoreAction(
|
||||||
|
this.storeActions.SAVE_WAITLIST_REQUESTED,
|
||||||
|
this.waitListRequested,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
this.$router.navigateWithSaving(this.navigationScenarios.CLICKED_FORWARD, this.$route);
|
||||||
},
|
},
|
||||||
|
setDisplayWaitList() {
|
||||||
|
if (
|
||||||
|
experimentMixin.methods.hasSettingEqualTo(
|
||||||
|
experimentSettings.DISPLAY_WAITLIST,
|
||||||
|
"true"
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
const dateString = this.selectableDatesData.days[0].date;
|
||||||
|
const [year, month, day] = dateString.split("-").map(Number);
|
||||||
|
const targetDate = new Date(year, month - 1, day);
|
||||||
|
const currentDate = new Date();
|
||||||
|
const futureDate = new Date(currentDate);
|
||||||
|
const experimentThresholdDays = experimentMixin.methods.hasSetting(
|
||||||
|
experimentSettings.WAITLIST_THRESHOLD_DAYS
|
||||||
|
)
|
||||||
|
? parseInt(
|
||||||
|
experimentMixin.methods.getSettingValue(
|
||||||
|
experimentSettings.WAITLIST_THRESHOLD_DAYS
|
||||||
|
)
|
||||||
|
)
|
||||||
|
: 0;
|
||||||
|
futureDate.setDate(currentDate.getDate() + experimentThresholdDays);
|
||||||
|
|
||||||
|
if (targetDate >= futureDate) {
|
||||||
|
this.displayWaitList = true;
|
||||||
|
} else {
|
||||||
|
this.displayWaitList = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
updateSupportingItems() {
|
updateSupportingItems() {
|
||||||
const supportingItems = this.getSupportingItems();
|
const supportingItems = this.getSupportingItems();
|
||||||
|
|
||||||
|
|
@ -532,6 +598,9 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handleWaitListRequested(value) {
|
||||||
|
this.waitListRequested = value;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
selectedDate(newValue, oldValue) {
|
selectedDate(newValue, oldValue) {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,21 @@
|
||||||
isRequired
|
isRequired
|
||||||
validationRules="time-slot-required" />
|
validationRules="time-slot-required" />
|
||||||
<div
|
<div
|
||||||
class="mt-1 mb-2 supplemental-information"
|
v-if="hasWaitListExperiment && displayWaitListFeature"
|
||||||
|
class="mt-5 bg-light rounded waitlist">
|
||||||
|
<textBlock
|
||||||
|
cmsWidgetName="WaitListLabelWidget"
|
||||||
|
typeStyle="medium"
|
||||||
|
fontWeight="600"
|
||||||
|
marginTopSizeOverride="0" />
|
||||||
|
<checkboxQuestion
|
||||||
|
class="mt-3"
|
||||||
|
cmsWidgetName="WaitListQuestionWidget"
|
||||||
|
v-model="waitListRequested"
|
||||||
|
@click="waitListChecked" />
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="mt-5 mb-2 supplemental-information"
|
||||||
v-if="supplementalInformationBlock"
|
v-if="supplementalInformationBlock"
|
||||||
v-html="supplementalInformationBlock"></div>
|
v-html="supplementalInformationBlock"></div>
|
||||||
<textBlock
|
<textBlock
|
||||||
|
|
@ -44,7 +58,11 @@
|
||||||
import modal from "@/digital-components/modal/modal";
|
import modal from "@/digital-components/modal/modal";
|
||||||
import textBlock from "@/digital-components/text-block/text-block";
|
import textBlock from "@/digital-components/text-block/text-block";
|
||||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
|
import checkboxQuestion from "@/digital-components/checkbox-question/checkbox-question";
|
||||||
import timeSlotModalListButton from "./time-slot-modal-list-button/time-slot-modal-list-button";
|
import timeSlotModalListButton from "./time-slot-modal-list-button/time-slot-modal-list-button";
|
||||||
|
import experimentMixin from "@/mixins/experiment-mixin";
|
||||||
|
import { experimentSettings } from "@/constants/experiments";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
// Helpers
|
// Helpers
|
||||||
import { deepClone } from "@/helpers/object-helper";
|
import { deepClone } from "@/helpers/object-helper";
|
||||||
|
|
@ -82,7 +100,7 @@ defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED));
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "time-slot-modal-question",
|
name: "time-slot-modal-question",
|
||||||
emits: ["update:modelValue", "TimeSlotSelected"],
|
emits: ["update:modelValue", "TimeSlotSelected", "click-event"],
|
||||||
props: {
|
props: {
|
||||||
modelValue: {
|
modelValue: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
@ -112,12 +130,14 @@ export default {
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
customComponentId: String,
|
customComponentId: String,
|
||||||
selectedDate: String,
|
selectedDate: String,
|
||||||
|
displayWaitList: Boolean,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
isModalOpened: false,
|
isModalOpened: false,
|
||||||
selectedRouteCode: this.getSelectedRouteCode(),
|
selectedRouteCode: this.getSelectedRouteCode(),
|
||||||
timeSlotModalListButton: timeSlotModalListButton,
|
timeSlotModalListButton: timeSlotModalListButton,
|
||||||
|
waitListRequested: this.getWaitListRequestedFromStore(),
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
|
|
@ -330,6 +350,15 @@ export default {
|
||||||
return this.getAvailableTimeSlotsForInshop(this.timeSlotsForSelectedDate.timeSlots);
|
return this.getAvailableTimeSlotsForInshop(this.timeSlotsForSelectedDate.timeSlots);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
hasWaitListExperiment() {
|
||||||
|
return experimentMixin.methods.hasSettingEqualTo(
|
||||||
|
experimentSettings.DISPLAY_WAITLIST,
|
||||||
|
"true"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
displayWaitListFeature() {
|
||||||
|
return this.displayWaitList;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openModal() {
|
openModal() {
|
||||||
|
|
@ -445,6 +474,9 @@ export default {
|
||||||
|
|
||||||
return selectedRouteCode;
|
return selectedRouteCode;
|
||||||
},
|
},
|
||||||
|
getWaitListRequestedFromStore() {
|
||||||
|
return store.getters.order.customer?.waitListRequested;
|
||||||
|
},
|
||||||
autoSelectTimeSlotIfOnlyOneIsAvailable() {
|
autoSelectTimeSlotIfOnlyOneIsAvailable() {
|
||||||
const numberOfOptions = this.availableTimeSlots?.length;
|
const numberOfOptions = this.availableTimeSlots?.length;
|
||||||
if (numberOfOptions === 1) {
|
if (numberOfOptions === 1) {
|
||||||
|
|
@ -493,6 +525,9 @@ export default {
|
||||||
isPremiumAppointment: null,
|
isPremiumAppointment: null,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
waitListChecked(event) {
|
||||||
|
this.$emit("waitListRequested-emitted", event.target.checked);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
unmounted() {
|
unmounted() {
|
||||||
if (this.isModalOpened) this.closeModal();
|
if (this.isModalOpened) this.closeModal();
|
||||||
|
|
@ -515,6 +550,7 @@ export default {
|
||||||
modal,
|
modal,
|
||||||
textBlock,
|
textBlock,
|
||||||
buttonQuestion,
|
buttonQuestion,
|
||||||
|
checkboxQuestion,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -538,5 +574,19 @@ export default {
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.waitlist {
|
||||||
|
box-shadow: 0px 1px 4px 0px #00000033;
|
||||||
|
border-radius: 8px;
|
||||||
|
font-size: $h6-font-size;
|
||||||
|
padding: 16px;
|
||||||
|
margin-top: 16px;
|
||||||
|
margin-bottom: -8px;
|
||||||
|
.ui-checkbox {
|
||||||
|
padding-left: 0px;
|
||||||
|
}
|
||||||
|
.form-check-input {
|
||||||
|
margin-left: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -42,11 +42,16 @@ export default {
|
||||||
await this.validateSession();
|
await this.validateSession();
|
||||||
|
|
||||||
const submittedOrder = baseMixin.methods.getSubmittedOrder();
|
const submittedOrder = baseMixin.methods.getSubmittedOrder();
|
||||||
|
const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder();
|
||||||
|
|
||||||
const refSequenceNum =
|
const refSequenceNum =
|
||||||
store.getters.order.referralSequenceNumber ||
|
store.getters.order.referralSequenceNumber ||
|
||||||
submittedOrder?.referralSequenceNumber;
|
submittedOrder?.referralSequenceNumber;
|
||||||
|
|
||||||
|
const parentAccountNum = hasSubmittedOrder
|
||||||
|
? submittedOrder.payment.parentAccountNumber
|
||||||
|
: store.getters.order.payment.parentAccountNumber;
|
||||||
|
|
||||||
var payload = {
|
var payload = {
|
||||||
userId: getUserIdValue(),
|
userId: getUserIdValue(),
|
||||||
sessionKey: getSessionKeyValue(),
|
sessionKey: getSessionKeyValue(),
|
||||||
|
|
@ -57,7 +62,7 @@ export default {
|
||||||
shouldUseSessionId: false,
|
shouldUseSessionId: false,
|
||||||
experimentsForUser: store.getters.applicationUser.experiments,
|
experimentsForUser: store.getters.applicationUser.experiments,
|
||||||
referralSequenceNumber: refSequenceNum,
|
referralSequenceNumber: refSequenceNum,
|
||||||
parentAccountNumber: store.getters.order.payment.parentAccountNumber,
|
parentAccountNumber: parentAccountNum,
|
||||||
};
|
};
|
||||||
|
|
||||||
await baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false);
|
await baseMixin.methods.dispatchStoreAction(storeActions.LOG_PAGE_VIEW, payload, false);
|
||||||
|
|
|
||||||
|
|
@ -98,6 +98,7 @@ const getDefaultState = () => {
|
||||||
emailAddress: null,
|
emailAddress: null,
|
||||||
phoneNumber: null,
|
phoneNumber: null,
|
||||||
isSmsOptIn: null,
|
isSmsOptIn: null,
|
||||||
|
waitListRequested: null,
|
||||||
},
|
},
|
||||||
damage: {
|
damage: {
|
||||||
isRepair: null,
|
isRepair: null,
|
||||||
|
|
@ -346,6 +347,9 @@ export const mutations = {
|
||||||
updateCustomerIsSmsOptin(state, isSmsOptIn) {
|
updateCustomerIsSmsOptin(state, isSmsOptIn) {
|
||||||
state.order.customer.isSmsOptIn = isSmsOptIn;
|
state.order.customer.isSmsOptIn = isSmsOptIn;
|
||||||
},
|
},
|
||||||
|
updateCustomerWaitListRequested(state, waitListRequested) {
|
||||||
|
state.order.customer.waitListRequested = waitListRequested;
|
||||||
|
},
|
||||||
updateVehicle(state, vehicleInfo) {
|
updateVehicle(state, vehicleInfo) {
|
||||||
state.order.vehicle.year = vehicleInfo.year;
|
state.order.vehicle.year = vehicleInfo.year;
|
||||||
state.order.vehicle.make = vehicleInfo.make;
|
state.order.vehicle.make = vehicleInfo.make;
|
||||||
|
|
@ -3081,6 +3085,10 @@ export const actions = {
|
||||||
context.commit(storeMutations.UPDATE_CUSTOMER_IS_SMS_OPT_IN, isSmsOptIn);
|
context.commit(storeMutations.UPDATE_CUSTOMER_IS_SMS_OPT_IN, isSmsOptIn);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
saveWaitListRequested(context, waitListRequested) {
|
||||||
|
context.commit(storeMutations.UPDATE_CUSTOMER_WAITLIST_REQUESTED, waitListRequested);
|
||||||
|
},
|
||||||
|
|
||||||
savePageData(context, emailOrSms) {
|
savePageData(context, emailOrSms) {
|
||||||
context.commit(storeMutations.UPDATE_PAGE_DATA, emailOrSms);
|
context.commit(storeMutations.UPDATE_PAGE_DATA, emailOrSms);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue