From f7bb4f3736103c1c0048124e640eb7573a8176b7 Mon Sep 17 00:00:00 2001 From: Johnny shultz Date: Mon, 23 Jun 2025 17:31:53 -0400 Subject: [PATCH 01/69] CASH-816 CASH-816 progress so far --- .../service-location/service-location.vue | 28 +- .../service-zip-modal-question.vue | 2 + .../service-zip-question.vue | 11 +- .../shop-question/shop-question-popup.vue | 615 ++++++++++++++++++ .../shop-question/shop-question.vue | 24 +- 5 files changed, 670 insertions(+), 10 deletions(-) create mode 100644 src/layouts/service-location/shop-question/shop-question-popup.vue diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 6893ad9b4..f9787a0e0 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -107,14 +107,27 @@ @setMobileLocation="setMobileLocationQuestions" @set-mobile-location-invalid="setMobileLocationInValid" /> - + cmsWidgetName="YourSafeliteShopWidget" /> --> + + + + @@ -137,6 +150,7 @@ import serviceZipModalQuestion from "@/layouts/service-location/service-zip-moda import mobileLocationModalQuestions from "@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions"; import appointmentTypeQuestion from "@/layouts/service-location/appointment-type-question/appointment-type-question"; import shopQuestion from "@/layouts/service-location/shop-question/shop-question"; +import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup"; import funnelHeader from "@/fmg-components/funnel-header/funnel-header"; import navbar from "@/fmg-components/nav-bar/nav-bar"; @@ -763,6 +777,13 @@ export default { setMobileLocationInValid(isMobileLocationInValid) { this.isMobileAddressValid = !isMobileLocationInValid; }, + onShopSelected(providerNumber) { + // Find the provider object from your shopProviderData + const selectedProvider = this.shopProviderData.shopProviders.find( + (p) => p.providerNumber === providerNumber + ); + this.selectedProvider = selectedProvider; + }, }, watch: { zipCode: { @@ -814,7 +835,8 @@ export default { Form, loadingModal, contentGroupModal, - shopQuestion, + //shopQuestion, + shopQuestionPopup, }, }; diff --git a/src/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue b/src/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue index 5e7aa73e4..0bbfbadf4 100644 --- a/src/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue +++ b/src/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue @@ -49,6 +49,7 @@ import textLink from "@/ux-components/text-link/text-link"; import serviceZipQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question"; import modal from "@/digital-components/modal/modal"; import alert from "@/ux-components/alert/alert"; +import shopQuestion from "@/layouts/service-location/shop-question/shop-question"; import { getPricedMobileFeePart, @@ -245,6 +246,7 @@ export default { serviceZipQuestion, modal, alert, + // shopQuestion }, }; diff --git a/src/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue b/src/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue index 9841c5b16..a0a43dc14 100644 --- a/src/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue +++ b/src/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue @@ -8,8 +8,8 @@ cornerStyle="rounded" mask="#####" :displayQuestionText="false" - isRequired - validationRules="zip-required|zip-format" /> + :isRequired="isRequired" + :validationRules="computedValidationRules" /> + + diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index 5a9278d78..d1dc3a24c 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -20,7 +20,7 @@ v-model="selectedProviderNumber" isRequired validationRules="option-required" /> - + @click-event="getNextShopsFromList(1)" + :aria-label="showMoreShopsLinkText" /> --> @@ -41,6 +41,8 @@ import alert from "@/ux-components/alert/alert"; import buttonQuestion from "@/digital-components/button-question/button-question"; import shopListButton from "./shop-list-button/shop-list-button"; import textLink from "@/ux-components/text-link/text-link"; +//import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup"; +//import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question"; // Supporting files import { defineRule } from "vee-validate"; @@ -125,7 +127,7 @@ export default { }, }, methods: { - async getNextShopsFromList(numberToGet = 3) { + async getNextShopsFromList(numberToGet = 1) { const logFirstShopsDisplayed = this.shopIndex == 0; const shopIterator = (array, n) => { @@ -234,6 +236,13 @@ export default { await nextTick(); } }, + onShopSelectedFromPopup(providerNumber) { + // Option 1: Update local state and emit up + this.$emit("shop-selected", providerNumber); + + // Option 2: If you want to update local state only, do: + // this.pendingSelectedProvider = providerNumber; + }, }, watch: { selectedAppointmentType: { @@ -258,8 +267,13 @@ export default { components: { alert, buttonQuestion, - textLink, + //textLink, + //shopQuestionPopup, + //serviceZipModalQuestion, }, + // mounted(){ + // console.log("shopProviderData" + this.shopProviderData); + // } }; From 059c5bc25a700c8674f864fcca40bbbb27a8feaf Mon Sep 17 00:00:00 2001 From: Chris Redelinghuys Date: Wed, 25 Jun 2025 14:57:02 -0400 Subject: [PATCH 02/69] CASH-952: Afterpay banner update --- src/constants/experiments.js | 1 + src/helpers/cms-content-helper.js | 4 + .../afterpay-modal-banner.vue | 110 ++++++++++++------ src/layouts/quote/quote.vue | 19 ++- src/styles/ux-variables.scss | 8 +- 5 files changed, 91 insertions(+), 51 deletions(-) diff --git a/src/constants/experiments.js b/src/constants/experiments.js index 871c6fd24..6a2796da9 100644 --- a/src/constants/experiments.js +++ b/src/constants/experiments.js @@ -26,6 +26,7 @@ const experimentSettings = { FOSTER_LOVE: "DisplayFosterLove", SKIP_TO_INSURANCE: "SkipToInsurance", DISPLAY_AFTERPAY_BREAKOUT_DISPLAY: "Display_AfterpayBreakoutDisplay", + AFTERPAY_EXTENDED_PAY_OPTION_THRESHOLD: "AfterPayExtendedPayOptionThreshold", DYNAMO_LOGGING: "DynamoLogging", }; diff --git a/src/helpers/cms-content-helper.js b/src/helpers/cms-content-helper.js index c1d28097a..727add296 100644 --- a/src/helpers/cms-content-helper.js +++ b/src/helpers/cms-content-helper.js @@ -339,3 +339,7 @@ export function splitCMSCopyOnParagraphTag(copy) { // filter removes empty strings that are a result of string.split with regex return copy.split(/(?:)|(?:<\/p>)/g).filter((paragraph) => paragraph !== ""); } + +export function splitCMSCopyOnBR(copy) { + return copy.split("
"); +} diff --git a/src/layouts/quote/afterpay-modal-banner/afterpay-modal-banner.vue b/src/layouts/quote/afterpay-modal-banner/afterpay-modal-banner.vue index 4c3644cac..32960509c 100644 --- a/src/layouts/quote/afterpay-modal-banner/afterpay-modal-banner.vue +++ b/src/layouts/quote/afterpay-modal-banner/afterpay-modal-banner.vue @@ -1,13 +1,14 @@ diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index f9787a0e0..0d7aa9e24 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -23,6 +23,7 @@ @updated-serviceability="setServiceabilityDetails" @updated-contains-military-base="setContainsMilitaryBase" @updated-bill-to-account-number="setBillToAccountNumber" + @updated-zipcode-ctu="setZipcodeCtu" linkWidgetName="ServiceZipLinkWidget" modalWidgetName="ServiceZipModalWidget" /> @@ -107,25 +108,36 @@ @setMobileLocation="setMobileLocationQuestions" @set-mobile-location-invalid="setMobileLocationInValid" /> - - - + @@ -151,6 +163,9 @@ import mobileLocationModalQuestions from "@/layouts/service-location/mobile-loca import appointmentTypeQuestion from "@/layouts/service-location/appointment-type-question/appointment-type-question"; import shopQuestion from "@/layouts/service-location/shop-question/shop-question"; import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup"; +import buttonQuestion from "@/digital-components/button-question/button-question.vue"; +import shopListButton from "@/layouts/service-location/shop-question/shop-list-button/shop-list-button"; +import { getAvailabilityRating } from "@/layouts/service-location/helpers/service-location-helper/service-location-helper"; import funnelHeader from "@/fmg-components/funnel-header/funnel-header"; import navbar from "@/fmg-components/nav-bar/nav-bar"; @@ -236,6 +251,7 @@ export default { shopProviderData: null, navigatingForward: false, isMobileAddressValid: true, + shopListButton: shopListButton, }; }, async beforeRouteEnter(to, from, next) { @@ -443,6 +459,54 @@ export default { isForwardActionDisabled() { return this.displayNoShopsAlert || !this.isMobileAddressValid; }, + additionalButtonData() { + const startDate = new Date(); + const endDate = new Date(); + endDate.setDate(startDate.getDate() + 6); + + const formattedStartDate = startDate.toISOString().split("T")[0]; + const formattedEndDate = endDate.toISOString().split("T")[0]; + + return { + availabilityRatingCallback: getAvailabilityRating, + startDate: formattedStartDate, + endDate: formattedEndDate, + shopAppointmentType: this.selectedAppointmentType, + }; + }, + selectedShopAnswer() { + const toTitleCase = (str) => { + if (!str) return ""; + return str.replace(/\w\S*/g, function (txt) { + return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase(); + }); + }; + + if (this.selectedProvider && this.selectedProvider.address) { + const provider = this.shopProviderData?.shopProviders?.find( + (p) => p.providerNumber === this.selectedProvider?.providerNumber + ); + const streetAddress = toTitleCase(this.selectedProvider.address.streetAddress); + const city = toTitleCase(this.selectedProvider.address.city); + const state = this.selectedProvider.address.state; + const zipCode = this.selectedProvider.address.zipCode; + const distanceInMiles = provider ? Math.round(provider.distanceInMiles * 2) / 2 : 0; + + return [ + { + buttonLabel: `${city}`, + buttonLabelSubCopy: `${distanceInMiles} mi`, + buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`, + //additionalButtonData: this.additionalButtonData, + value: this.selectedProvider.providerNumber, + }, + ]; + } + return []; + }, + questionText() { + return this.getCmsContent("YourSafeliteShopWidget", "QuestionText"); + }, }, methods: { arePagePrerequisitesValid() { @@ -726,8 +790,6 @@ export default { this.selectedProvider.address.zipCode = null; this.selectedProvider.address.zipCodeCtu = null; } else { - // if we have a provider.zipCodeCtu that's different than the servicelocation.zipCodeCtu then they - // may have selected a shop in a different ctu. change the servicelocation zip/ctu if different if (this.zipCodeCtu != this.selectedProvider.address.zipCodeCtu) { ctu = this.selectedProvider.address.zipCodeCtu; } @@ -777,12 +839,59 @@ export default { setMobileLocationInValid(isMobileLocationInValid) { this.isMobileAddressValid = !isMobileLocationInValid; }, - onShopSelected(providerNumber) { - // Find the provider object from your shopProviderData - const selectedProvider = this.shopProviderData.shopProviders.find( - (p) => p.providerNumber === providerNumber + onShopSelected(providerObject) { + const current = this.shopProviderData?.shopProviders?.find( + (p) => p.providerNumber === this.selectedProvider?.providerNumber ); - this.selectedProvider = selectedProvider; + if (current) { + this.selectedProvider = current; + } + + let provider = this.shopProviderData?.shopProviders?.find( + (p) => p.providerNumber === providerObject?.providerNumber + ); + if (!provider && this.shopProviderData?.shopProviders?.length > 0) { + provider = this.shopProviderData.shopProviders[0]; + } + this.selectedProvider = provider; + if (provider && provider.address) { + this.zipCode = provider.address.zipCode; + this.state = provider.address.state; + } + if ( + !this.selectedProvider || + !this.shopProviderData?.shopProviders?.some( + (p) => p.providerNumber === this.selectedProvider?.providerNumber + ) + ) { + this.selectedProvider = this.shopProviderData?.shopProviders?.[0]; + } + if (providerObject && providerObject.address) { + this.zipCode = providerObject.address.zipCode; + this.state = providerObject.address.state; + } + }, + setZipcodeCtu(zipcodeCtu) { + this.zipCodeCtu = zipcodeCtu; + }, + onShopModelUpdated(newModel) { + if (newModel.zipCode) { + this.zipCode = newModel.zipCode; + } + if (newModel.zipCodeCtu) { + this.zipCodeCtu = newModel.zipCodeCtu; + } + if (newModel.state) { + this.state = newModel.state; + } + if (this.shopProviderData && newModel.selectedProviderNumber) { + const provider = this.shopProviderData.shopProviders.find( + (p) => p.providerNumber === newModel.selectedProviderNumber + ); + if (provider) { + this.selectedProvider = provider; + } + } }, }, watch: { @@ -796,7 +905,7 @@ export default { this.shopProviderData.mobileProviderNumber ); } else { - this.selectedProvider = new Provider(); + this.isMobileAddressValid = true; } }); } @@ -819,7 +928,7 @@ export default { } this.$refs.mobileLocationQuestions.resetAlerts(); } else { - this.selectedProvider = new Provider(); + this.selectedProvider = this.shopProviderData.shopProviders[0]; } }, }, @@ -835,8 +944,8 @@ export default { Form, loadingModal, contentGroupModal, - //shopQuestion, shopQuestionPopup, + buttonQuestion, }, }; @@ -861,4 +970,8 @@ export default { color: $black; } } +.shop-question-button .list-button-content { + background: #e4f1f7 !important; + box-shadow: 0 0 0 1px $primary !important; +} diff --git a/src/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue b/src/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue index a0a43dc14..8fe355923 100644 --- a/src/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue +++ b/src/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue @@ -7,6 +7,8 @@ questionAlignment="center" cornerStyle="rounded" mask="#####" + :includeSearchIcon="includeSearchIcon" + @search-icon-click="$emit('search-icon-click')" :displayQuestionText="false" :isRequired="isRequired" :validationRules="computedValidationRules" /> @@ -35,6 +37,10 @@ export default { type: Boolean, default: true, }, + includeSearchIcon: { + type: Boolean, + default: false, + }, }, computed: { value: { diff --git a/src/layouts/service-location/shop-question/shop-question-popup.vue b/src/layouts/service-location/shop-question/shop-question-popup.vue index c3ea91faf..8da980863 100644 --- a/src/layouts/service-location/shop-question/shop-question-popup.vue +++ b/src/layouts/service-location/shop-question/shop-question-popup.vue @@ -8,29 +8,6 @@ cmsWidgetName="AlertDropoffInformationWidget" alertClass="alert-info" v-bind:isDismissible="false" /> - - @@ -149,6 +156,11 @@ export default { required: false, default: false, }, + insertOrLabelBeforeFinalOption: { + type: Boolean, + required: false, + default: false, + }, }, setup(props) { const propsClone = Object.assign({}, props); @@ -390,4 +402,16 @@ export default { } } } +.or-label { + width: 100%; + text-align: center; + border-bottom: 1px solid black; + line-height: 1px; + margin: 10px 0 20px; + + span { + background: #fff; + padding: 0 10px; + } +} diff --git a/src/digital-components/date-picker/date-picker.vue b/src/digital-components/date-picker/date-picker.vue index 3d517fd85..642c90174 100644 --- a/src/digital-components/date-picker/date-picker.vue +++ b/src/digital-components/date-picker/date-picker.vue @@ -1373,7 +1373,7 @@ export default { } } } - :deep(.button-inner-wrapper) { + :deep(.timeslots .button-inner-wrapper) { display: flex; max-width: 100%; flex-wrap: wrap; 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..e3d2ef691 100644 --- a/src/layouts/schedule/time-slot-question/time-slot-question.vue +++ b/src/layouts/schedule/time-slot-question/time-slot-question.vue @@ -7,11 +7,30 @@ justifyText="center" typeStyle="small" class="duration-text-block" /> + +
+ +
+
{ + return this.isDropOffRouteCode(timeSlot.id); + }) + .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, + buttonLabel: buttonLabelValue, + }; + }); + if ( + this.getAvailableTimeSlotsForInshop(this.timeSlotsForSelectedDate.timeSlots) + .length !== 0 + ) { + dropOffQuestionAnswers.push({ + value: PICK_A_TIME_BUTTON_VALUE, + buttonLabel: "Pick a time", + }); + } + return dropOffQuestionAnswers; + }, hasWaitListExperiment() { return experimentMixin.methods.hasSettingEqualTo( experimentSettings.DISPLAY_WAITLIST, @@ -360,6 +411,33 @@ export default { isDropOffAppointment() { return this.appointmentType === AppointmentTypeStrings.DROP_OFF; }, + shouldDisplayDropOffAlert() { + return this.isDropOffRouteCode(this.selectedAnswerForDropOff); + }, + dropOffTimeSlotAlertCMSWidgetName() { + if (this.selectedAnswerForDropOff.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { + return "OvernightDropOffTimeSlotAlert"; + } else if (this.isSameDay) { + return "SameDayDropOffTimeSlotAlert"; + } else { + return "DropOffTimeSlotAlert"; + } + }, + isDropOffAppointmentAvailable() { + console.log("its running"); + + return ( + this.answersForDropOffQuestion !== null && + this.answersForDropOffQuestion.length !== 0 && + this.answersForDropOffQuestion[0].value !== PICK_A_TIME_BUTTON_VALUE + ); + }, + shouldDisplayTimeSlotQuestion() { + return ( + this.selectedAnswerForDropOff == PICK_A_TIME_BUTTON_VALUE || + !this.isDropOffAppointmentAvailable + ); + }, }, methods: { async setSelectedTimeSlot() { @@ -382,31 +460,17 @@ export default { } }, getAvailableTimeSlotsForInshop(timeSlotsForSelectedDate) { - return timeSlotsForSelectedDate.map((timeSlot) => { - 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)) { - buttonLabelValue = this.overnightDropoffButtonText; - } else if (this.isSameDay) { - buttonLabelValue = this.sameDayDropoffButtonText; - } else { - buttonLabelValue = this.dropoffButtonText; - } - return { - value: timeSlot.id, - buttonLabel: buttonLabelValue, - }; - }); - - return availableTimeSlots; + return timeSlotsForSelectedDate + .filter((timeSlot) => { + return !this.isDropOffRouteCode(timeSlot.id); + }) + .map((timeSlot) => { + const readableTime = militaryToTwelveHourTime(timeSlot.startTime); + return { + value: timeSlot.id, + buttonLabel: readableTime, + }; + }); }, getAvailableTimeSlotsForMobile(timeSlotsForSelectedDate) { const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot) => { @@ -463,9 +527,14 @@ export default { return store.getters.order.customer?.waitListRequested; }, autoSelectTimeSlotIfOnlyOneIsAvailable() { - const numberOfOptions = this.availableTimeSlots?.length; + console.log(this.timeSlotsForSelectedDate.timeSlots?.length); + const numberOfOptions = this.timeSlotsForSelectedDate.timeSlots?.length; if (numberOfOptions === 1) { - this.selectedRouteCode = this.availableTimeSlots[0].value; + if (this.availableTimeSlots.length > 0) { + this.selectedAnswerForTimeSlots = this.availableTimeSlots[0].value; + } else { + this.selectedAnswerForDropOff = this.answersForDropOffQuestion[0].value; + } } }, addPremiumFlagToInput(routeCode) { @@ -519,6 +588,12 @@ export default { successMessageElement.scrollIntoView({ behavior: "smooth" }); } }, + isDropOffRouteCode(routeCode) { + return ( + routeCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF) || + routeCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF) + ); + }, }, watch: { waitListRequested(newVal) { @@ -545,12 +620,24 @@ export default { this.setSelectedTimeSlot(); } }, + selectedAnswerForDropOff(newValue) { + if (newValue == PICK_A_TIME_BUTTON_VALUE) { + this.selectedRouteCode = null; + } else { + this.selectedAnswerForTimeSlots = null; + this.selectedRouteCode = newValue; + } + }, + selectedAnswerForTimeSlots(newValue) { + if (newValue) this.selectedRouteCode = newValue; + }, }, components: { // Removed modal textBlock, buttonQuestion, checkboxQuestion, + alert, }, }; @@ -623,5 +710,23 @@ export default { text-align: left; margin: 1.5rem 0 0; } + .drop-off-alert { + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_13957_112512)'%3E%3Cpath d='M5.99865 0C4.81147 4.82643e-07 3.65095 0.352111 2.66392 1.01179C1.67688 1.67146 0.907678 2.60907 0.45361 3.70599C-0.000459241 4.80291 -0.11899 6.00986 0.113013 7.17415C0.345015 8.33845 0.917126 9.40778 1.75697 10.2469C2.59682 11.086 3.66666 11.6571 4.83117 11.8881C5.99567 12.119 7.20251 11.9994 8.29902 11.5443C9.39553 11.0893 10.3324 10.3192 10.9912 9.33159C11.65 8.34396 12.0011 7.18313 12 5.99594C11.9971 4.40566 11.3638 2.88142 10.2388 1.75742C9.11375 0.633431 7.58894 0.00143011 5.99865 0V0ZM5.99865 11.2478C4.96135 11.2473 3.94748 10.9392 3.08518 10.3627C2.22288 9.7861 1.55085 8.96685 1.15401 8.00846C0.75718 7.05006 0.653353 5.99554 0.855656 4.97815C1.05796 3.96077 1.55731 3.02618 2.29061 2.29251C3.0239 1.55884 3.95823 1.059 4.97551 0.856176C5.99279 0.653349 7.04737 0.756633 8.00597 1.15297C8.96457 1.54931 9.78416 2.22092 10.3612 3.08293C10.9382 3.94493 11.2467 4.95864 11.2478 5.99594C11.2478 7.38835 10.6949 8.72377 9.71053 9.70861C8.7262 10.6934 7.39106 11.2471 5.99865 11.2478V11.2478Z' fill='%2306577C'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.22736 8.84695C6.30613 8.76818 6.35038 8.66135 6.35038 8.54996V5.30996C6.35038 5.19857 6.30613 5.09174 6.22736 5.01298C6.1486 4.93421 6.04177 4.88996 5.93038 4.88996C5.81899 4.88996 5.71216 4.93421 5.63339 5.01298C5.55463 5.09174 5.51038 5.19857 5.51038 5.30996V8.54996C5.51038 8.66135 5.55463 8.76818 5.63339 8.84695C5.71216 8.92571 5.81899 8.96996 5.93038 8.96996C6.04177 8.96996 6.1486 8.92571 6.22736 8.84695ZM5.69704 3.97918C5.76611 4.02533 5.84731 4.04996 5.93038 4.04996C5.98558 4.05012 6.04026 4.03936 6.09129 4.01831C6.14232 3.99726 6.18868 3.96633 6.22771 3.9273C6.26675 3.88827 6.29768 3.8419 6.31873 3.79088C6.33978 3.73985 6.35053 3.68516 6.35038 3.62996C6.35038 3.54689 6.32574 3.46569 6.27959 3.39662C6.23344 3.32755 6.16785 3.27372 6.0911 3.24193C6.01436 3.21014 5.92991 3.20183 5.84844 3.21803C5.76697 3.23424 5.69213 3.27424 5.63339 3.33298C5.57465 3.39171 5.53465 3.46655 5.51845 3.54802C5.50224 3.6295 5.51056 3.71394 5.54235 3.79069C5.57414 3.86743 5.62797 3.93303 5.69704 3.97918Z' fill='%2306577C'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_13957_112512'%3E%3Crect width='12' height='12' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A"); + background-repeat: no-repeat; + background-size: 0.75rem; + background-position: 0.5rem 0.75rem; + border-radius: 0.5rem; + display: flex; + flex-direction: row; + padding: 0.5rem 0.5rem 0.5rem 1.5rem; + gap: 0.25rem; + background-color: #e4f1f7; + + .alert-heading { + text-align: left; + font-size: 0.75rem; + line-height: 1.25rem; + } + } } diff --git a/src/layouts/service-location/shop-question/shop-question.vue b/src/layouts/service-location/shop-question/shop-question.vue index 5a9278d78..7191a1f07 100644 --- a/src/layouts/service-location/shop-question/shop-question.vue +++ b/src/layouts/service-location/shop-question/shop-question.vue @@ -277,23 +277,24 @@ export default { margin-top: 0.5rem; } } -} -.drop-off-alert { - background: url("data:image/svg+xml,%3Csvg viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_13957_112512)'%3E%3Cpath d='M5.99865 0C4.81147 4.82643e-07 3.65095 0.352111 2.66392 1.01179C1.67688 1.67146 0.907678 2.60907 0.45361 3.70599C-0.000459241 4.80291 -0.11899 6.00986 0.113013 7.17415C0.345015 8.33845 0.917126 9.40778 1.75697 10.2469C2.59682 11.086 3.66666 11.6571 4.83117 11.8881C5.99567 12.119 7.20251 11.9994 8.29902 11.5443C9.39553 11.0893 10.3324 10.3192 10.9912 9.33159C11.65 8.34396 12.0011 7.18313 12 5.99594C11.9971 4.40566 11.3638 2.88142 10.2388 1.75742C9.11375 0.633431 7.58894 0.00143011 5.99865 0V0ZM5.99865 11.2478C4.96135 11.2473 3.94748 10.9392 3.08518 10.3627C2.22288 9.7861 1.55085 8.96685 1.15401 8.00846C0.75718 7.05006 0.653353 5.99554 0.855656 4.97815C1.05796 3.96077 1.55731 3.02618 2.29061 2.29251C3.0239 1.55884 3.95823 1.059 4.97551 0.856176C5.99279 0.653349 7.04737 0.756633 8.00597 1.15297C8.96457 1.54931 9.78416 2.22092 10.3612 3.08293C10.9382 3.94493 11.2467 4.95864 11.2478 5.99594C11.2478 7.38835 10.6949 8.72377 9.71053 9.70861C8.7262 10.6934 7.39106 11.2471 5.99865 11.2478V11.2478Z' fill='%2306577C'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.22736 8.84695C6.30613 8.76818 6.35038 8.66135 6.35038 8.54996V5.30996C6.35038 5.19857 6.30613 5.09174 6.22736 5.01298C6.1486 4.93421 6.04177 4.88996 5.93038 4.88996C5.81899 4.88996 5.71216 4.93421 5.63339 5.01298C5.55463 5.09174 5.51038 5.19857 5.51038 5.30996V8.54996C5.51038 8.66135 5.55463 8.76818 5.63339 8.84695C5.71216 8.92571 5.81899 8.96996 5.93038 8.96996C6.04177 8.96996 6.1486 8.92571 6.22736 8.84695ZM5.69704 3.97918C5.76611 4.02533 5.84731 4.04996 5.93038 4.04996C5.98558 4.05012 6.04026 4.03936 6.09129 4.01831C6.14232 3.99726 6.18868 3.96633 6.22771 3.9273C6.26675 3.88827 6.29768 3.8419 6.31873 3.79088C6.33978 3.73985 6.35053 3.68516 6.35038 3.62996C6.35038 3.54689 6.32574 3.46569 6.27959 3.39662C6.23344 3.32755 6.16785 3.27372 6.0911 3.24193C6.01436 3.21014 5.92991 3.20183 5.84844 3.21803C5.76697 3.23424 5.69213 3.27424 5.63339 3.33298C5.57465 3.39171 5.53465 3.46655 5.51845 3.54802C5.50224 3.6295 5.51056 3.71394 5.54235 3.79069C5.57414 3.86743 5.62797 3.93303 5.69704 3.97918Z' fill='%2306577C'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_13957_112512'%3E%3Crect width='12' height='12' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A"); - background-repeat: no-repeat; - background-size: 0.75rem; - background-position: 0.5rem 0.75rem; - border-radius: 0.5rem; - display: flex; - flex-direction: row; - padding: 0.5rem 0.5rem 0.5rem 1.5rem; - gap: 0.25rem; + .drop-off-alert { + background: url("data:image/svg+xml,%3Csvg viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_13957_112512)'%3E%3Cpath d='M5.99865 0C4.81147 4.82643e-07 3.65095 0.352111 2.66392 1.01179C1.67688 1.67146 0.907678 2.60907 0.45361 3.70599C-0.000459241 4.80291 -0.11899 6.00986 0.113013 7.17415C0.345015 8.33845 0.917126 9.40778 1.75697 10.2469C2.59682 11.086 3.66666 11.6571 4.83117 11.8881C5.99567 12.119 7.20251 11.9994 8.29902 11.5443C9.39553 11.0893 10.3324 10.3192 10.9912 9.33159C11.65 8.34396 12.0011 7.18313 12 5.99594C11.9971 4.40566 11.3638 2.88142 10.2388 1.75742C9.11375 0.633431 7.58894 0.00143011 5.99865 0V0ZM5.99865 11.2478C4.96135 11.2473 3.94748 10.9392 3.08518 10.3627C2.22288 9.7861 1.55085 8.96685 1.15401 8.00846C0.75718 7.05006 0.653353 5.99554 0.855656 4.97815C1.05796 3.96077 1.55731 3.02618 2.29061 2.29251C3.0239 1.55884 3.95823 1.059 4.97551 0.856176C5.99279 0.653349 7.04737 0.756633 8.00597 1.15297C8.96457 1.54931 9.78416 2.22092 10.3612 3.08293C10.9382 3.94493 11.2467 4.95864 11.2478 5.99594C11.2478 7.38835 10.6949 8.72377 9.71053 9.70861C8.7262 10.6934 7.39106 11.2471 5.99865 11.2478V11.2478Z' fill='%2306577C'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.22736 8.84695C6.30613 8.76818 6.35038 8.66135 6.35038 8.54996V5.30996C6.35038 5.19857 6.30613 5.09174 6.22736 5.01298C6.1486 4.93421 6.04177 4.88996 5.93038 4.88996C5.81899 4.88996 5.71216 4.93421 5.63339 5.01298C5.55463 5.09174 5.51038 5.19857 5.51038 5.30996V8.54996C5.51038 8.66135 5.55463 8.76818 5.63339 8.84695C5.71216 8.92571 5.81899 8.96996 5.93038 8.96996C6.04177 8.96996 6.1486 8.92571 6.22736 8.84695ZM5.69704 3.97918C5.76611 4.02533 5.84731 4.04996 5.93038 4.04996C5.98558 4.05012 6.04026 4.03936 6.09129 4.01831C6.14232 3.99726 6.18868 3.96633 6.22771 3.9273C6.26675 3.88827 6.29768 3.8419 6.31873 3.79088C6.33978 3.73985 6.35053 3.68516 6.35038 3.62996C6.35038 3.54689 6.32574 3.46569 6.27959 3.39662C6.23344 3.32755 6.16785 3.27372 6.0911 3.24193C6.01436 3.21014 5.92991 3.20183 5.84844 3.21803C5.76697 3.23424 5.69213 3.27424 5.63339 3.33298C5.57465 3.39171 5.53465 3.46655 5.51845 3.54802C5.50224 3.6295 5.51056 3.71394 5.54235 3.79069C5.57414 3.86743 5.62797 3.93303 5.69704 3.97918Z' fill='%2306577C'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_13957_112512'%3E%3Crect width='12' height='12' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A"); + background-repeat: no-repeat; + background-size: 0.75rem; + background-position: 0.5rem 0.75rem; + border-radius: 0.5rem; + display: flex; + flex-direction: row; + padding: 0.5rem 0.5rem 0.5rem 1.5rem; + gap: 0.25rem; + background-color: #e4f1f7; - .alert-heading { - text-align: left; - font-size: 0.75rem; - line-height: 1.25rem; + .alert-heading { + text-align: left; + font-size: 0.75rem; + line-height: 1.25rem; + } } } From b311f6d41c26eec32e13694901d6d8e668bf8d31 Mon Sep 17 00:00:00 2001 From: Bryan Mauger Date: Thu, 3 Jul 2025 10:33:25 -0400 Subject: [PATCH 25/69] CASH-959 update hop font-weights. --- public/css/hop-styling.css | 9 +++++---- public/scss/hop-styling.scss | 9 +++++---- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/public/css/hop-styling.css b/public/css/hop-styling.css index a79c2f049..41fc1edd5 100644 --- a/public/css/hop-styling.css +++ b/public/css/hop-styling.css @@ -12,7 +12,7 @@ body { padding: 8px; } body h3 { - font-weight: 600; + font-weight: 700; } body .validation-info { display: none; @@ -35,7 +35,7 @@ body .form-group { body .headerlinecontainer .headerline1 { font-size: 20px; line-height: 32px; - font-weight: 500; + font-weight: 400; margin: 24px 0; text-align: center; } @@ -96,7 +96,7 @@ body .creditCardSpecific div .headerlinecontainer { display: none; } body .creditCardSpecific div label { - font-weight: 600; + font-weight: 500; } body .creditCardSpecific #infoRow2 { margin-bottom: 0; @@ -140,6 +140,7 @@ body .buttonContainer button { border-radius: 8px; color: #fff; justify-content: center; + font-family: Urbanist, Arial, Helvetica, sans-serif; font-weight: 500; font-size: 16px; height: 48px; @@ -272,7 +273,7 @@ body .cc-error-container #alert-message { #fmg-checkout-shared #other-payments-container label span.paymentOptionText { margin: auto 0; padding-left: 0; - font-weight: 600; + font-weight: 400; } #fmg-checkout-shared #other-payments-container #afterpayParentLink label > span:first-of-type { width: 100%; diff --git a/public/scss/hop-styling.scss b/public/scss/hop-styling.scss index 3d30255cc..bb38cf6b9 100644 --- a/public/scss/hop-styling.scss +++ b/public/scss/hop-styling.scss @@ -12,7 +12,7 @@ body { padding: 8px; h3 { - font-weight: 600; + font-weight: 700; } .validation-info { @@ -42,7 +42,7 @@ body { .headerline1 { font-size: 20px; line-height: 32px; - font-weight: 500; + font-weight: 400; margin: 24px 0; text-align: center; } @@ -103,7 +103,7 @@ body { display: none; } label { - font-weight: 600; + font-weight: 500; } } #infoRow2 { @@ -151,6 +151,7 @@ body { border-radius: 8px; color: #fff; justify-content: center; + font-family: Urbanist, Arial, Helvetica, sans-serif; font-weight: 500; font-size: 16px; height: 48px; @@ -330,7 +331,7 @@ body { &.paymentOptionText { margin: auto 0; padding-left: 0; - font-weight: 600; + font-weight: 400; } } } From e3e6b27148c531941290b37b5704d07e10ad7cd5 Mon Sep 17 00:00:00 2001 From: Bryan Mauger Date: Thu, 3 Jul 2025 13:01:32 -0400 Subject: [PATCH 26/69] CASH-1127 update hop font. --- public/css/hop-styling.css | 2 ++ public/scss/hop-styling.scss | 2 ++ 2 files changed, 4 insertions(+) diff --git a/public/css/hop-styling.css b/public/css/hop-styling.css index 41fc1edd5..0318d52ff 100644 --- a/public/css/hop-styling.css +++ b/public/css/hop-styling.css @@ -51,6 +51,8 @@ body select { font-size: 16px; color: #000; background-color: #fff; + font-family: Urbanist, Arial, Helvetica, sans-serif; + font-weight: 400; } body input:focus, body input:focus-visible, body select:focus, diff --git a/public/scss/hop-styling.scss b/public/scss/hop-styling.scss index bb38cf6b9..aae9913e2 100644 --- a/public/scss/hop-styling.scss +++ b/public/scss/hop-styling.scss @@ -61,6 +61,8 @@ body { font-size: 16px; color: #000; background-color: #fff; + font-family: Urbanist, Arial, Helvetica, sans-serif; + font-weight: 400; &:focus, &:focus-visible { box-shadow: 0 0 0 2.5px #1574a1; From 76d67981f6a6e3dd430a1ddbb9288062f519bac8 Mon Sep 17 00:00:00 2001 From: AdamCaouetteSafelite Date: Thu, 3 Jul 2025 14:44:39 -0400 Subject: [PATCH 27/69] CASH-845 router change refactor --- src/router/constants/routes.js | 9 ++++----- src/router/methods/helpers/handle-heritage-return.js | 9 --------- src/router/methods/route-logic/service-location.js | 8 ++++++++ src/router/methods/routes.js | 4 ++-- 4 files changed, 14 insertions(+), 16 deletions(-) create mode 100644 src/router/methods/route-logic/service-location.js diff --git a/src/router/constants/routes.js b/src/router/constants/routes.js index 45fdfb243..6fec2455d 100644 --- a/src/router/constants/routes.js +++ b/src/router/constants/routes.js @@ -55,11 +55,10 @@ export const routeData = { name: "insurance-company", path: "/insurance-company", }, - // TODO: REMOVE THIS COMMENT AND BELOW, ONCE CASH-803 (SERVICE-LOCATION AND SCHEDULE PAGE COMBINATION) HAS BEEN VETTED - // SERVICE_LOCATION: { - // name: "service-location", - // path: "/service-location", - // }, + SERVICE_LOCATION: { // keep even though this page has been removed from the regular flow bc Heritage still points to it + name: "service-location", + path: "/service-location", + }, HERITAGE: { name: "heritage", path: "/virtual/heritage", diff --git a/src/router/methods/helpers/handle-heritage-return.js b/src/router/methods/helpers/handle-heritage-return.js index 6d8c60a58..74a1ce62a 100644 --- a/src/router/methods/helpers/handle-heritage-return.js +++ b/src/router/methods/helpers/handle-heritage-return.js @@ -1,7 +1,6 @@ import { queryStrings } from "@/constants/query-strings"; import { consumeReferralQuerystrings } from "@/router/methods/helpers/consume-referral-info"; import { loadSessionIfPresent } from "@/helpers/heritage-integration/order-helper"; -import router from "@/router"; import { routeData } from "@/router/constants/routes"; export async function handleHeritageReturn(to, from) { @@ -13,13 +12,5 @@ export async function handleHeritageReturn(to, from) { // load session with new cookie await loadSessionIfPresent(true, routeData.SCHEDULE.name); - - // Temporary redirect until URLs to old service-location page can be updated in Heritage - if (to.fullPath.includes("fmgPage=service-location")) { - // Redirect to Schedule page - router.push({ - name: routeData.SCHEDULE.name, - }); - } } } diff --git a/src/router/methods/route-logic/service-location.js b/src/router/methods/route-logic/service-location.js new file mode 100644 index 000000000..ecaebe149 --- /dev/null +++ b/src/router/methods/route-logic/service-location.js @@ -0,0 +1,8 @@ +import { routeData } from "@/router/constants/routes"; + +export async function serviceLocationBeforeEnter(to, from) { + return { + name: routeData.SCHEDULE.name, + replace: true, + }; +} diff --git a/src/router/methods/routes.js b/src/router/methods/routes.js index 83fbb3811..97af04068 100644 --- a/src/router/methods/routes.js +++ b/src/router/methods/routes.js @@ -12,6 +12,7 @@ import { errorBeforeEnter } from "@/router/methods/route-logic/error"; import { restartBeforeEnter } from "@/router/methods/route-logic/restart"; import { paymentMethodBeforeEnter } from "@/router/methods/route-logic/payment-method"; import { paymentBeforeEnter } from "@/router/methods/route-logic/payment"; +import { serviceLocationBeforeEnter } from "@/router/methods/route-logic/service-location"; export const routes = [ // Non-virtual pages. @@ -29,8 +30,7 @@ export const routes = [ createRoute(routeData.CAPABILITY_QUESTIONS), createRoute(routeData.QUOTE, quoteBeforeEnter), createRoute(routeData.INSURANCE_COMPANY, insuranceCompanyBeforeEnter), - // TODO: REMOVE THIS COMMENT AND BELOW, ONCE CASH-803 (SERVICE-LOCATION AND SCHEDULE PAGE COMBINATION) HAS BEEN VETTED - // createRoute(routeData.SERVICE_LOCATION), + createRoute(routeData.SERVICE_LOCATION, serviceLocationBeforeEnter), createRoute(routeData.SCHEDULE), createRoute(routeData.CUSTOMER_DETAILS), createRoute(routeData.PAYMENT_METHOD, paymentMethodBeforeEnter), From 13b8e7f7373d95b42c1e2bff8a03d5b4994070f6 Mon Sep 17 00:00:00 2001 From: AdamCaouetteSafelite Date: Thu, 3 Jul 2025 14:46:48 -0400 Subject: [PATCH 28/69] CASH-845 restore handle-heritage-return completely --- src/router/methods/helpers/handle-heritage-return.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/router/methods/helpers/handle-heritage-return.js b/src/router/methods/helpers/handle-heritage-return.js index 74a1ce62a..7914c8e0e 100644 --- a/src/router/methods/helpers/handle-heritage-return.js +++ b/src/router/methods/helpers/handle-heritage-return.js @@ -11,6 +11,6 @@ export async function handleHeritageReturn(to, from) { await consumeReferralQuerystrings(); // load session with new cookie - await loadSessionIfPresent(true, routeData.SCHEDULE.name); + await loadSessionIfPresent(true, routeData.SERVICE_LOCATION.name); } } From fc088ecd08a65907e61171bc3d7c5140b0a575ec Mon Sep 17 00:00:00 2001 From: AdamCaouetteSafelite Date: Thu, 3 Jul 2025 14:49:59 -0400 Subject: [PATCH 29/69] CASH-845: prettier change --- src/router/constants/routes.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/router/constants/routes.js b/src/router/constants/routes.js index 6fec2455d..5632fe357 100644 --- a/src/router/constants/routes.js +++ b/src/router/constants/routes.js @@ -55,7 +55,8 @@ export const routeData = { name: "insurance-company", path: "/insurance-company", }, - SERVICE_LOCATION: { // keep even though this page has been removed from the regular flow bc Heritage still points to it + SERVICE_LOCATION: { + // keep even though this page has been removed from the regular flow bc Heritage still points to it name: "service-location", path: "/service-location", }, From 9f37c2cf42dd547eeef234af55c16c2ff9b96b3e Mon Sep 17 00:00:00 2001 From: AdamCaouetteSafelite Date: Thu, 3 Jul 2025 15:17:05 -0400 Subject: [PATCH 30/69] CASH-845 stage 2: update pagePrerequisites --- src/layouts/schedule/schedule.spec.js | 10 ++- src/layouts/schedule/schedule.vue | 90 ++++++++++++++++++++------- 2 files changed, 75 insertions(+), 25 deletions(-) diff --git a/src/layouts/schedule/schedule.spec.js b/src/layouts/schedule/schedule.spec.js index 60d20b6e7..b3404f611 100644 --- a/src/layouts/schedule/schedule.spec.js +++ b/src/layouts/schedule/schedule.spec.js @@ -176,6 +176,9 @@ beforeEach(() => { isRepair: false, }, referralNumber: "1234567", + policy: { + policyNumber: "123", + }, }, payment: { isInsurance: true, @@ -195,11 +198,12 @@ afterEach(() => { describe("schedule.vue...", () => { describe("initial load", () => { - test("should pass arePagePrerequisitesValid with a mobile order and no providerNumber", () => { + test("should pass arePagePrerequisitesValid with a mobile CASH order and no providerNumber", () => { // Arrange const { wrapper } = setupMocks({}); store.getters.order.serviceLocation.appointmentType = "Mobile"; - store.getters.order.serviceLocation.provider = null; + store.getters.order.serviceLocation.provider.policyNumber = null; + store.getters.payment.isInsurance = false; // Act const arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid(); @@ -208,7 +212,7 @@ describe("schedule.vue...", () => { expect(arePagePrerequisitesValid).toBe(true); }); - test("should pass arePagePrerequisitesValid with a inshop order and providerNumber", () => { + test("should pass arePagePrerequisitesValid with an inshop order and providerNumber", () => { // Arrange const { wrapper } = setupMocks({}); diff --git a/src/layouts/schedule/schedule.vue b/src/layouts/schedule/schedule.vue index ee2096c36..5de235275 100644 --- a/src/layouts/schedule/schedule.vue +++ b/src/layouts/schedule/schedule.vue @@ -91,6 +91,7 @@ import { getItemsWithoutRecalParts } from "@/helpers/recal-helper"; import { partNumberStrings } from "@/constants/part-number-strings"; import { deepClone } from "@/helpers/object-helper"; import { debugLog } from "@/helpers/debug-log-helper"; +import { applicationConfig } from "@/constants/application-config"; // DEFINE VALIDATION RULES defineRule("date-required", required(errorMessages.DATE_REQUIRED)); @@ -367,12 +368,13 @@ export default { const resultMap = await settleAllPromises(promiseResultMap); - const pricingByDayUpcharge = showPricingByDay - ? await baseMixin.methods.getTotalLineItemPrice( - resultMap.pricingByDayUpchargePart, - false - ) - : null; + const pricingByDayUpcharge = + showPricingByDay && resultMap.pricingByDayUpchargePart + ? await baseMixin.methods.getTotalLineItemPrice( + resultMap.pricingByDayUpchargePart, + false + ) + : null; const datePickerInitialData = resultMap.datePickerInitialData; datePickerInitialData.pricingByDayBasePrice = pricingByDayBasePrice; @@ -480,32 +482,76 @@ export default { methods: { splitCopyOnCMSPlaceHolder, arePagePrerequisitesValid() { - const serviceLocation = store.getters.order.serviceLocation; // TODO - MAY NEED TO REMOVE THIS AS A PREREQ - - const serviceLocationPreReqs = serviceLocation.zipCode && serviceLocation.zipCodeCtu; // TODO - MAY NEED TO ADD IN SERVICE LOCATION PREREQS HERE TOO - const paymentInfo = store.getters.payment.isInsurance !== null; - const damageInfo = store.getters.order.damage.isRepair || (store.getters.order.lineItems?.glassParts != null && store.getters.order.lineItems.glassParts.length > 0); + const parentAccountNumberInfo = + store.getters.payment.parentAccountNumber !== + applicationConfig.CASH_PARENT_ACCOUNT_NUMBER; + const policyNumberInfo = store.getters.order.policy.policyNumber; + const zipCodeInfo = store.getters.order.serviceLocation.zipCode; + const supportingItemsInfo = store.getters.lineItems.supportingItems; - const preReqResult = serviceLocationPreReqs && paymentInfo && damageInfo; + // insurance drops the recycle fee on replace orders so it won't be in supportingItems + const insurancePreReqResult = + parentAccountNumberInfo && + policyNumberInfo && + zipCodeInfo && + paymentInfo && + damageInfo; + const cashPreReqResult = + supportingItemsInfo && zipCodeInfo && paymentInfo && damageInfo; - // prettier-ignore - { + const outputDebugLog = (preReqResult) => { + // prettier-ignore debugLog("--- schedule.vue pagePrereqs start ---", null, !preReqResult); - debugLog("store.getters.order.serviceLocation.zipCode:", serviceLocation.zipCode, !preReqResult); - debugLog("store.getters.order.serviceLocation.zipCodeCtu:", serviceLocation.zipCodeCtu, !preReqResult); - debugLog("store.getters.order.serviceLocation.appointmentType:", serviceLocation.appointmentType, !preReqResult); - debugLog("store.getters.order.serviceLocation.provider.providerNumber:", serviceLocation.provider?.providerNumber, !preReqResult); - debugLog("store.getters.payment.isInsurance:", store.getters.payment?.isInsurance, !preReqResult); - debugLog("store.getters.order.damage.isRepair:", store.getters.order.damage?.isRepair, !preReqResult); - debugLog("store.getters.order.lineItems.glassParts:", store.getters.order.lineItems?.glassParts, !preReqResult); + debugLog( + "store.getters.payment.isInsurance:", + store.getters.payment?.isInsurance, + !preReqResult + ); + debugLog( + "store.getters.order.damage.isRepair:", + store.getters.order.damage?.isRepair, + !preReqResult + ); + debugLog( + "store.getters.order.lineItems.glassParts:", + store.getters.order.lineItems?.glassParts, + !preReqResult + ); + debugLog( + "store.getters.payment.parentAccountNumber:", + store.getters.payment.parentAccountNumber, + !preReqResult + ); + debugLog( + "store.getters.order.policy.policyNumber:", + store.getters.order.policy.policyNumber, + !preReqResult + ); + debugLog( + "store.getters.order.serviceLocation.zipCode:", + store.getters.order.serviceLocation.zipCode, + !preReqResult + ); + debugLog( + "store.getters.lineItems.supportingItems:", + store.getters.lineItems.supportingItems, + !preReqResult + ); debugLog("--- schedule.vue pagePrereqs end ---", null, !preReqResult); + }; + + if (store.getters.payment.isInsurance) { + outputDebugLog(insurancePreReqResult); + return insurancePreReqResult; + } else { + outputDebugLog(cashPreReqResult); + return cashPreReqResult; } - return preReqResult; }, async getMoreScheduleData(startDate, endDate) { // called only when "View more dates" is clicked; not on initial page load From c1a5dcdeef1c4fe8cd3ba82ddb48e0afe4971672 Mon Sep 17 00:00:00 2001 From: Scott Kiener Date: Mon, 7 Jul 2025 12:13:08 -0400 Subject: [PATCH 31/69] CASH-814 | Styling, cleanup, auto select, CMS integration --- .../button-question/button-question.vue | 2 +- .../date-picker/date-picker.spec.js | 2 +- .../date-picker/date-picker.vue | 2 + .../time-slot-question/time-slot-question.vue | 79 +++++++++---------- 4 files changed, 40 insertions(+), 45 deletions(-) diff --git a/src/digital-components/button-question/button-question.vue b/src/digital-components/button-question/button-question.vue index dc1f50c15..2eaf204ad 100644 --- a/src/digital-components/button-question/button-question.vue +++ b/src/digital-components/button-question/button-question.vue @@ -407,7 +407,7 @@ export default { text-align: center; border-bottom: 1px solid black; line-height: 1px; - margin: 10px 0 20px; + margin: 20px 0 20px; span { background: #fff; diff --git a/src/digital-components/date-picker/date-picker.spec.js b/src/digital-components/date-picker/date-picker.spec.js index e1fbf302f..09bf21d76 100644 --- a/src/digital-components/date-picker/date-picker.spec.js +++ b/src/digital-components/date-picker/date-picker.spec.js @@ -481,7 +481,7 @@ describe("date-picker.vue", () => { }, }); const spy = jest.spyOn(wrapper.vm, "setCalendarData"); - + wrapper.vm.$refs.timeSlotModalQuestion.initializeComponent = jest.fn(); wrapper.vm.$nextTick(); // Act diff --git a/src/digital-components/date-picker/date-picker.vue b/src/digital-components/date-picker/date-picker.vue index e008021db..8f6b35f60 100644 --- a/src/digital-components/date-picker/date-picker.vue +++ b/src/digital-components/date-picker/date-picker.vue @@ -140,6 +140,7 @@ dropoffCmsWidgetName="DropOffTimeSlotModal" sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal" overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal" + dropOffOrPickATimeQuestionCmsWidgetName="DropOffOrPickATimeQuestionWidget" :selectedDate="selectedDate" :appointmentType="appointmentType" :premiumAppointmentFee="premiumAppointmentFee" @@ -292,6 +293,7 @@ export default { methods: { initializeComponent(initialData) { this.setCalendarData(initialData); + this.$refs.timeSlotModalQuestion.initializeComponent(); }, fireDateSelectedEvent(event, date) { // Ignore if arrow key selected radioButton 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 2d67ddc90..80d22cae5 100644 --- a/src/layouts/schedule/time-slot-question/time-slot-question.vue +++ b/src/layouts/schedule/time-slot-question/time-slot-question.vue @@ -10,7 +10,7 @@ { - let buttonLabelValue; - if (timeSlot.id.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) { - buttonLabelValue = this.dropoffButtonText; - } else if (timeSlot.id.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) { - buttonLabelValue = this.overnightDropoffButtonText; - } else if (this.isSameDay) { - buttonLabelValue = this.sameDayDropoffButtonText; - } else { - buttonLabelValue = militaryToTwelveHourTime(timeSlot.startTime); - } - return { - value: timeSlot.id, - buttonLabel: buttonLabelValue, - }; - }); - - return availableTimeSlots; - }, getAvailableTimeSlotsForMobile(timeSlotsForSelectedDate) { const availableTimeSlots = timeSlotsForSelectedDate.map((timeSlot) => { const readableTime = `${militaryToTwelveHourTime(timeSlot.startTime)} - ${militaryToTwelveHourTime( @@ -529,27 +520,27 @@ export default { }, }; }, - getSelectedRouteCode() { - let selectedRouteCode; + setSelectedRouteCodeFromParent() { if (!this.modelValue?.timeSlot) { - selectedRouteCode = null; + return; } - + const routeCodeFromParent = this.modelValue.timeSlot.routeCode; if (this.modelValue?.isPremiumAppointment) { - selectedRouteCode = this.addPremiumFlagToInput( - this.modelValue?.timeSlot?.routeCode - ); + // Mobile Only + this.selectedAnswerForTimeSlots = this.addPremiumFlagToInput(routeCodeFromParent); } else { - selectedRouteCode = this.modelValue?.timeSlot?.routeCode; + if (this.isDropOffRouteCode(routeCodeFromParent)) { + this.selectedAnswerForDropOff = routeCodeFromParent; + } else { + this.selectedAnswerForDropOff = PICK_A_TIME_BUTTON_VALUE; + this.selectedAnswerForTimeSlots = routeCodeFromParent; + } } - - return selectedRouteCode; }, getWaitListRequestedFromStore() { return store.getters.order.customer?.waitListRequested; }, autoSelectTimeSlotIfOnlyOneIsAvailable() { - console.log(this.timeSlotsForSelectedDate.timeSlots?.length); const numberOfOptions = this.timeSlotsForSelectedDate.timeSlots?.length; if (numberOfOptions === 1) { if (this.availableTimeSlots.length > 0) { @@ -570,7 +561,6 @@ export default { if (routeCodeIncludesPremium) { routeCode = this.removePremiumFlagFromInput(routeCode); } - const timeSlot = this.timeSlotsForSelectedDate?.timeSlots?.find( (slot) => slot.id == routeCode ); @@ -611,6 +601,9 @@ export default { } }, isDropOffRouteCode(routeCode) { + if (!routeCode) { + return false; + } return ( routeCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF) || routeCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF) From ba1217d36c27c760efa7368f2d549a1162e8dda6 Mon Sep 17 00:00:00 2001 From: Johnny shultz Date: Tue, 8 Jul 2025 11:25:11 -0400 Subject: [PATCH 32/69] CASH-816 CASH-816 clean up, defect fixes, looks to be running smoothly now --- src/digital-components/modal/modal.vue | 5 + .../service-location/service-location.vue | 23 +- .../shop-question/shop-question-popup.vue | 291 +++++++++++------- 3 files changed, 183 insertions(+), 136 deletions(-) diff --git a/src/digital-components/modal/modal.vue b/src/digital-components/modal/modal.vue index 4cc75f701..55feca36f 100644 --- a/src/digital-components/modal/modal.vue +++ b/src/digital-components/modal/modal.vue @@ -36,6 +36,7 @@ :id="modalId + '-modalbtn'" ref="modalButtonMain" loaderColor="white" + :isDisabled="footerButtonDisabled" :buttonText="footerButtonText" @click-event="validateAndEmit" :class="isFooterButtonDisabled && 'form-test-invalid'" /> @@ -59,6 +60,7 @@ export default { footerButtonText: String, suppressPageScroll: Boolean, staticBackdrop: Boolean, + footerButtonDisabled: Boolean, onModalOpenedCallback: { type: Function, }, @@ -137,6 +139,9 @@ export default { }, computed: { isFooterButtonDisabled() { + if (this.footerButtonDisabled !== undefined) { + return this.footerButtonDisabled; + } if (!this.meta.touched) { return !this.meta.valid; } diff --git a/src/layouts/service-location/service-location.vue b/src/layouts/service-location/service-location.vue index 776fe1199..329b99840 100644 --- a/src/layouts/service-location/service-location.vue +++ b/src/layouts/service-location/service-location.vue @@ -115,9 +115,9 @@ :selectedAppointmentType="selectedAppointmentType" :modelValue="{ zipCode: zipCode, - providerNumber: selectedProvider?.providerNumber, + state: state, }" - :preselectedProviderNumber="selectedProvider?.providerNumber" + :preSelectedProviderNumber="selectedProvider?.providerNumber" :shopProviderData="shopProviderData" :isServiceableInshop="isServiceableInshop" @updated-serviceability="setServiceabilityDetails" @@ -844,25 +844,10 @@ export default { let provider = this.shopProviderData?.shopProviders?.find( (p) => p.providerNumber === providerObject?.providerNumber ); - if (!provider && this.shopProviderData?.shopProviders?.length > 0) { - provider = this.shopProviderData.shopProviders[0]; - } this.selectedProvider = provider; - if (provider && provider.address) { - this.zipCode = provider.address.zipCode; - this.state = provider.address.state; - } - if ( - !this.selectedProvider || - !this.shopProviderData?.shopProviders?.some( - (p) => p.providerNumber === this.selectedProvider?.providerNumber - ) - ) { - this.selectedProvider = this.shopProviderData?.shopProviders?.[0]; - } if (providerObject && providerObject.address) { - this.zipCode = providerObject.address.zipCode; - this.state = providerObject.address.state; + this.zipCode = providerObject.searchedZip; + this.state = providerObject.searchedState; } }, setZipcodeCtu(zipcodeCtu) { diff --git a/src/layouts/service-location/shop-question/shop-question-popup.vue b/src/layouts/service-location/shop-question/shop-question-popup.vue index b345d370d..9f7507d77 100644 --- a/src/layouts/service-location/shop-question/shop-question-popup.vue +++ b/src/layouts/service-location/shop-question/shop-question-popup.vue @@ -24,22 +24,29 @@ :onModalOpenedCallback="onModalOpened" :onModalClosedCallback="onModalClosed" :footerButtonText="modalFooterText" + :footerButtonDisabled=" + displayInvalidZipAlert || displayNoShopsAlert || !selectedProviderNumber + " @footer-button-event="SetZipCodeAndShop"> -
-
- -
-
+ + - -