From aafc3d15df65c7f7ba82103478212d70b00e0f58 Mon Sep 17 00:00:00 2001 From: Scott Kiener Date: Thu, 26 Jun 2025 09:37:35 -0400 Subject: [PATCH 1/6] CASH-814 | Combine drop-off and in-shop time slots Changed name of component because it was named based on functionality that no longer exists (no-modal is a confusing way to name everything that isn't a modal) Cleaned up references to DROP_OFF that are obsolete --- .../time-slot-question/time-slot-question.vue | 50 +++++++++---------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/src/layouts/schedule/time-slot-question/time-slot-question.vue b/src/layouts/schedule/time-slot-question/time-slot-question.vue index 58648746e..bba09e785 100644 --- a/src/layouts/schedule/time-slot-question/time-slot-question.vue +++ b/src/layouts/schedule/time-slot-question/time-slot-question.vue @@ -14,7 +14,6 @@ class="mt-4" :class="[ isMobileAppointment ? 'is-mobile-appointment' : '', - isDropOffAppointment ? 'is-drop-off-appointment' : '', ]" :answers="availableTimeSlots" groupName="chooseTimeSlot" @@ -97,7 +96,7 @@ const cmsWidgetFieldMappings = { defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED)); export default { - name: "time-slot-no-modal-question", + name: "time-slot-question", emits: ["update:modelValue", "TimeSlotSelected", "click-event"], props: { modelValue: { @@ -240,7 +239,10 @@ export default { ); }, disclaimerTextBlockCopy() { - if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { + /* AppointmentTypeStrings.DROP_OFF should never be used per CASH-803 epic + but I'm leaving this in assuming that a future card in this epic + will handle disclaimers in a different way */ + if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { if (this.selectedRouteCode?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { if (this.isSameDay) { return this.sameDayDropOffDisclaimerText; @@ -329,11 +331,7 @@ export default { return null; } - if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { - return this.getAvailableTimeSlotsForDropOff( - this.timeSlotsForSelectedDate.timeSlots - ); - } else if (this.appointmentType === AppointmentTypeStrings.MOBILE) { + if (this.appointmentType === AppointmentTypeStrings.MOBILE) { return this.getAvailableTimeSlotsForMobile(this.timeSlotsForSelectedDate.timeSlots); } else { return this.getAvailableTimeSlotsForInshop(this.timeSlotsForSelectedDate.timeSlots); @@ -356,10 +354,7 @@ export default { }, isMobileAppointment() { return this.appointmentType === AppointmentTypeStrings.MOBILE; - }, - isDropOffAppointment() { - return this.appointmentType === AppointmentTypeStrings.DROP_OFF; - }, + } }, methods: { async setSelectedTimeSlot() { @@ -382,23 +377,20 @@ export default { } }, getAvailableTimeSlotsForInshop(timeSlotsForSelectedDate) { - return timeSlotsForSelectedDate.map((timeSlot) => { + let dropOffIndex = -1; + const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot, index) => { const readableTime = militaryToTwelveHourTime(timeSlot.startTime); - return { - value: timeSlot.id, - buttonLabel: readableTime, - }; - }); - }, - getAvailableTimeSlotsForDropOff(timeSlotsForSelectedDate) { - const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot) => { - let buttonLabelValue; - if (timeSlot.id.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { + let buttonLabelValue = readableTime; + if (timeSlot.id.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { + dropOffIndex = index; + if (this.isSameDay) { + buttonLabelValue = this.sameDayDropoffButtonText; + } else { + buttonLabelValue = this.dropoffButtonText; + } + } else if (timeSlot.id.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { + dropOffIndex = index; buttonLabelValue = this.overnightDropoffButtonText; - } else if (this.isSameDay) { - buttonLabelValue = this.sameDayDropoffButtonText; - } else { - buttonLabelValue = this.dropoffButtonText; } return { value: timeSlot.id, @@ -406,6 +398,10 @@ export default { }; }); + if (dropOffIndex) { + const dropOffTimeSlot = availableTimeSlots.splice(dropOffIndex, 1)[0]; + availableTimeSlots.unshift(dropOffTimeSlot); + } return availableTimeSlots; }, getAvailableTimeSlotsForMobile(timeSlotsForSelectedDate) { From b7b0f388f72121a07bef1c541871074ebcde4dcb Mon Sep 17 00:00:00 2001 From: Scott Kiener Date: Thu, 26 Jun 2025 09:42:05 -0400 Subject: [PATCH 2/6] CASH-814 | Formatting --- .../schedule/time-slot-question/time-slot-question.vue | 8 +++----- src/styles/ux-variables.scss | 4 ++-- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/src/layouts/schedule/time-slot-question/time-slot-question.vue b/src/layouts/schedule/time-slot-question/time-slot-question.vue index bba09e785..f0499e11a 100644 --- a/src/layouts/schedule/time-slot-question/time-slot-question.vue +++ b/src/layouts/schedule/time-slot-question/time-slot-question.vue @@ -12,9 +12,7 @@ buttonTypeString="timeSlotModalListButton" :buttonTypeObject="timeSlotModalListButton" class="mt-4" - :class="[ - isMobileAppointment ? 'is-mobile-appointment' : '', - ]" + :class="[isMobileAppointment ? 'is-mobile-appointment' : '']" :answers="availableTimeSlots" groupName="chooseTimeSlot" textPosition="text-center" @@ -242,7 +240,7 @@ export default { /* AppointmentTypeStrings.DROP_OFF should never be used per CASH-803 epic but I'm leaving this in assuming that a future card in this epic will handle disclaimers in a different way */ - if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { + if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { if (this.selectedRouteCode?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { if (this.isSameDay) { return this.sameDayDropOffDisclaimerText; @@ -354,7 +352,7 @@ export default { }, isMobileAppointment() { return this.appointmentType === AppointmentTypeStrings.MOBILE; - } + }, }, methods: { async setSelectedTimeSlot() { diff --git a/src/styles/ux-variables.scss b/src/styles/ux-variables.scss index 69ba0d7ac..01b122b31 100644 --- a/src/styles/ux-variables.scss +++ b/src/styles/ux-variables.scss @@ -121,8 +121,8 @@ $body-color: $gray-600; //Fonts $font-family-sans-serif: UrbanistRegular, Arial, Helvetica, sans-serif; -$font-family-monospace: UrbanistRegular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", - monospace; +$font-family-monospace: + UrbanistRegular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; // stylelint-enable value-keyword-case $font-family-base: $font-family-sans-serif; $font-family-code: $font-family-monospace; From a736f9395408258fc528b1036cae41dcbb1bd73f Mon Sep 17 00:00:00 2001 From: Chris Redelinghuys Date: Thu, 26 Jun 2025 10:50:11 -0400 Subject: [PATCH 3/6] CASH-955: Add copy to Afterpay calculator --- .../afterpay-breakout/afterpay-breakout.vue | 8 ++++++++ src/styles/ux-variables.scss | 1 + 2 files changed, 9 insertions(+) diff --git a/src/layouts/payment-method/afterpay-breakout/afterpay-breakout.vue b/src/layouts/payment-method/afterpay-breakout/afterpay-breakout.vue index 9e98eb9c3..68d9baf2f 100644 --- a/src/layouts/payment-method/afterpay-breakout/afterpay-breakout.vue +++ b/src/layouts/payment-method/afterpay-breakout/afterpay-breakout.vue @@ -82,6 +82,8 @@ Amount Due + +

6 or 12 monthly payment plans available

@@ -208,6 +210,12 @@ export default { overflow: hidden; opacity: 0; visibility: hidden; + + > p { + padding-top: 1rem; + font-size: $font-size-12; + margin: 0; + } } } .payment-section { diff --git a/src/styles/ux-variables.scss b/src/styles/ux-variables.scss index 178d50d35..22e17e3b7 100644 --- a/src/styles/ux-variables.scss +++ b/src/styles/ux-variables.scss @@ -130,6 +130,7 @@ $font-family-base: $font-family-sans-serif; $font-family-code: $font-family-monospace; $font-size-base: 1rem; // Assumes the browser default, typically `16px` +$font-size-12: $font-size-base * 0.75; // 12px $font-size-20: $font-size-base * 1.25; // 20px //Custom Font size (extra small) From ef9c0eeebafa132747bce8c08204169b2bbb3810 Mon Sep 17 00:00:00 2001 From: CarlNation Date: Thu, 26 Jun 2025 11:17:20 -0400 Subject: [PATCH 4/6] CASH-1029 CASH-1029 add exposure flag --- src/mixins/analytics-mixin.js | 10 +++++----- src/store/index.js | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/mixins/analytics-mixin.js b/src/mixins/analytics-mixin.js index 90513e764..72ede2538 100644 --- a/src/mixins/analytics-mixin.js +++ b/src/mixins/analytics-mixin.js @@ -132,7 +132,6 @@ export default { async logDigitalConsumer() { const currentPageName = getPageNameFromRouter(); const universes = store.getters.applicationUser.experiments; - console.log(JSON.stringify(universes)); let hasDynamoLogging = experimentMixin.methods.hasSettingEqualTo( experimentSettings.DYNAMO_LOGGING, @@ -150,15 +149,15 @@ export default { const conceptVariation = variationNames.length > 0 ? variationNames[0] : ""; + const isConceptExposed = universes.find( + (item) => item.universeName === experimentUniverses.CONCEPT_FUNNEL + )?.isExposed; + const submittedOrder = baseMixin.methods.getSubmittedOrder(); const hasSubmittedOrder = baseMixin.methods.hasSubmittedOrder(); const hasSubmittedOrderAtConfirmationPage = hasSubmittedOrder && currentPageName?.toLowerCase() == routeData.CONFIRMATION.name; - const refSequenceNum = hasSubmittedOrderAtConfirmationPage - ? submittedOrder.referralSequenceNumber - : store.getters.order.referralSequenceNumber; - var payload = { actionName: `Browser page:${currentPageName}`, referralSequenceNumber: hasSubmittedOrderAtConfirmationPage @@ -174,6 +173,7 @@ export default { ? submittedOrder.workOrderNumber : store.getters.order.workOrderNumber, conceptVariation: conceptVariation, + isConceptExposed: isConceptExposed, }; await baseMixin.methods.dispatchStoreAction( diff --git a/src/store/index.js b/src/store/index.js index 83d8d99af..61c38997c 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -1570,6 +1570,7 @@ export const actions = { workOrderId, workOrderNumber, conceptVariation, + isConceptExposed, } ) { var payload = { @@ -1582,6 +1583,7 @@ export const actions = { workOrderId: workOrderId ?? "", workOrderNumber: workOrderNumber ?? "", conceptVariation: conceptVariation, + isConceptExposed: isConceptExposed, }; return globalMethods.callHttpClient({ From 14e1be18d8c6cb78ae09869ac2e3d7c79731b60d Mon Sep 17 00:00:00 2001 From: Matt Caimi Date: Thu, 26 Jun 2025 14:53:00 -0400 Subject: [PATCH 5/6] CASH-926 amount due correction --- src/helpers/pricing-helper.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/pricing-helper.js b/src/helpers/pricing-helper.js index 33311fd21..9aa317353 100644 --- a/src/helpers/pricing-helper.js +++ b/src/helpers/pricing-helper.js @@ -67,7 +67,7 @@ export function getAmountDueWithDonation(lineItemsObject, donationLineItem) { // this is amount due with Donation added const lineItemsCloneWithDonation = deepClone(lineItemsObject); lineItemsCloneWithDonation.supportingItems.push(donationLineItem); - return getAmountDue(lineItemsCloneWithDonation, false); + return getAmountDue(lineItemsCloneWithDonation); } export async function getPricingByDayPartWithPrice(pageNameToLog) { From 8056eea2e2714e962f98227e0c345ce50f3c6f50 Mon Sep 17 00:00:00 2001 From: Scott Kiener Date: Fri, 27 Jun 2025 10:10:53 -0400 Subject: [PATCH 6/6] Revert "Merge pull request #2605 from Safelite/feature/Digital/CASH-814" This reverts commit 1e4ee3d544ab28df08521f1bdbb37403ec61303e, reversing changes made to 7cb65a585660919d4244a3439a00638ab7f71c36. --- .../time-slot-question/time-slot-question.vue | 50 +++++++++++-------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/layouts/schedule/time-slot-question/time-slot-question.vue b/src/layouts/schedule/time-slot-question/time-slot-question.vue index f0499e11a..58648746e 100644 --- a/src/layouts/schedule/time-slot-question/time-slot-question.vue +++ b/src/layouts/schedule/time-slot-question/time-slot-question.vue @@ -12,7 +12,10 @@ buttonTypeString="timeSlotModalListButton" :buttonTypeObject="timeSlotModalListButton" class="mt-4" - :class="[isMobileAppointment ? 'is-mobile-appointment' : '']" + :class="[ + isMobileAppointment ? 'is-mobile-appointment' : '', + isDropOffAppointment ? 'is-drop-off-appointment' : '', + ]" :answers="availableTimeSlots" groupName="chooseTimeSlot" textPosition="text-center" @@ -94,7 +97,7 @@ const cmsWidgetFieldMappings = { defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED)); export default { - name: "time-slot-question", + name: "time-slot-no-modal-question", emits: ["update:modelValue", "TimeSlotSelected", "click-event"], props: { modelValue: { @@ -237,9 +240,6 @@ export default { ); }, disclaimerTextBlockCopy() { - /* AppointmentTypeStrings.DROP_OFF should never be used per CASH-803 epic - but I'm leaving this in assuming that a future card in this epic - will handle disclaimers in a different way */ if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { if (this.selectedRouteCode?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { if (this.isSameDay) { @@ -329,7 +329,11 @@ export default { return null; } - if (this.appointmentType === AppointmentTypeStrings.MOBILE) { + if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) { + return this.getAvailableTimeSlotsForDropOff( + this.timeSlotsForSelectedDate.timeSlots + ); + } else if (this.appointmentType === AppointmentTypeStrings.MOBILE) { return this.getAvailableTimeSlotsForMobile(this.timeSlotsForSelectedDate.timeSlots); } else { return this.getAvailableTimeSlotsForInshop(this.timeSlotsForSelectedDate.timeSlots); @@ -353,6 +357,9 @@ export default { isMobileAppointment() { return this.appointmentType === AppointmentTypeStrings.MOBILE; }, + isDropOffAppointment() { + return this.appointmentType === AppointmentTypeStrings.DROP_OFF; + }, }, methods: { async setSelectedTimeSlot() { @@ -375,20 +382,23 @@ export default { } }, getAvailableTimeSlotsForInshop(timeSlotsForSelectedDate) { - let dropOffIndex = -1; - const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot, index) => { + return timeSlotsForSelectedDate.map((timeSlot) => { const readableTime = militaryToTwelveHourTime(timeSlot.startTime); - let buttonLabelValue = readableTime; - if (timeSlot.id.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { - dropOffIndex = index; - if (this.isSameDay) { - buttonLabelValue = this.sameDayDropoffButtonText; - } else { - buttonLabelValue = this.dropoffButtonText; - } - } else if (timeSlot.id.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { - dropOffIndex = index; + return { + value: timeSlot.id, + buttonLabel: readableTime, + }; + }); + }, + getAvailableTimeSlotsForDropOff(timeSlotsForSelectedDate) { + const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot) => { + let buttonLabelValue; + if (timeSlot.id.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { buttonLabelValue = this.overnightDropoffButtonText; + } else if (this.isSameDay) { + buttonLabelValue = this.sameDayDropoffButtonText; + } else { + buttonLabelValue = this.dropoffButtonText; } return { value: timeSlot.id, @@ -396,10 +406,6 @@ export default { }; }); - if (dropOffIndex) { - const dropOffTimeSlot = availableTimeSlots.splice(dropOffIndex, 1)[0]; - availableTimeSlots.unshift(dropOffTimeSlot); - } return availableTimeSlots; }, getAvailableTimeSlotsForMobile(timeSlotsForSelectedDate) {