Merge branch 'develop' into feature/CASH-1123
This commit is contained in:
commit
12baa76a49
28 changed files with 634 additions and 539 deletions
|
|
@ -110,18 +110,6 @@ stages:
|
|||
clearFolder: true
|
||||
deployFolder: ""
|
||||
region: us-east-2
|
||||
appDeployVariables:
|
||||
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||
__VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
|
||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||
__VUE_APP_MY_ACCOUNT__: $(__VUE_APP_MY_ACCOUNT__)
|
||||
__VUE_APP_SESSION_TIMEOUT_MINUTES__: $(__VUE_APP_SESSION_TIMEOUT_MINUTES__)
|
||||
indexDeployVariables:
|
||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||
__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__: $(__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__)
|
||||
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
||||
parameters:
|
||||
awsCliContainer: awscli
|
||||
|
|
@ -171,18 +159,6 @@ stages:
|
|||
clearFolder: true
|
||||
deployFolder: ""
|
||||
region: us-east-2
|
||||
appDeployVariables:
|
||||
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||
__VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
|
||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||
__VUE_APP_MY_ACCOUNT__: $(__VUE_APP_MY_ACCOUNT__)
|
||||
__VUE_APP_SESSION_TIMEOUT_MINUTES__: $(__VUE_APP_SESSION_TIMEOUT_MINUTES__)
|
||||
indexDeployVariables:
|
||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||
__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__: $(__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__)
|
||||
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
||||
parameters:
|
||||
awsCliContainer: awscli
|
||||
|
|
@ -232,18 +208,6 @@ stages:
|
|||
clearFolder: true
|
||||
deployFolder: ""
|
||||
region: us-east-2
|
||||
appDeployVariables:
|
||||
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||
__VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
|
||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||
__VUE_APP_MY_ACCOUNT__: $(__VUE_APP_MY_ACCOUNT__)
|
||||
__VUE_APP_SESSION_TIMEOUT_MINUTES__: $(__VUE_APP_SESSION_TIMEOUT_MINUTES__)
|
||||
indexDeployVariables:
|
||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||
__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__: $(__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__)
|
||||
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
||||
parameters:
|
||||
awsCliContainer: awscli
|
||||
|
|
@ -293,18 +257,6 @@ stages:
|
|||
clearFolder: true
|
||||
deployFolder: ""
|
||||
region: us-east-2
|
||||
appDeployVariables:
|
||||
__VUE_APP_CONSUMER_CF_DISTRO__: $(__VUE_APP_CONSUMER_CF_DISTRO__)
|
||||
__VUE_APP_GOOGLE_PLACES_API_KEY__: $(__VUE_APP_GOOGLE_PLACES_API_KEY__)
|
||||
__VUE_APP_HERITAGE_FUNNEL__: $(__VUE_APP_HERITAGE_FUNNEL__)
|
||||
__VUE_APP_SAFELITE_HOP__: $(__VUE_APP_SAFELITE_HOP__)
|
||||
__VUE_APP_CURRENT_ENVIRONMENT__: $(__VUE_APP_CURRENT_ENVIRONMENT__)
|
||||
__VUE_APP_MY_ACCOUNT__: $(__VUE_APP_MY_ACCOUNT__)
|
||||
__VUE_APP_SESSION_TIMEOUT_MINUTES__: $(__VUE_APP_SESSION_TIMEOUT_MINUTES__)
|
||||
indexDeployVariables:
|
||||
__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__: $(__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__)
|
||||
__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__: $(__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__)
|
||||
__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__: $(__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__)
|
||||
- template: templates/digital/invalidate-cloudfront-cache.yml@AzureDevOps
|
||||
parameters:
|
||||
awsCliContainer: awscli
|
||||
|
|
|
|||
23
environment-variables.js
Normal file
23
environment-variables.js
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
// DEFINE every environment variable we will use here,
|
||||
// with a default value to use in local development and unit tests.
|
||||
//
|
||||
// Default values will not be used when we deploy to prod or non-prod.
|
||||
const environmentVariables = {
|
||||
['__VUE_APP_CONSUMER_CF_DISTRO__']: "https://digitalapi.dev.safelite.io",
|
||||
['__VUE_APP_CURRENT_ENVIRONMENT__']: "Localhost",
|
||||
['__VUE_APP_GOOGLE_PLACES_API_KEY__']: "AIzaSyDptGCkOPgN2uWJOy4ou4M33phRD4MAoJo",
|
||||
['__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__']: "https://www.googletagmanager.com/ns.html?id=GTM-M6XCRH>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x",
|
||||
['__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__']: "(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl+ '>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x';f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-M6XCRH');",
|
||||
['__VUE_APP_HERITAGE_FUNNEL__']: "https://fixmyglassdev.safelite.com/default.aspx",
|
||||
['__VUE_APP_MY_ACCOUNT__']: "https://myaccountdev.safelite.com/",
|
||||
['__VUE_APP_SAFELITE_HOP__']: "https://sv2-safelitehop-dev.safelite.com/fmgCheckoutShared.aspx",
|
||||
['__VUE_APP_SESSION_TIMEOUT_MINUTES__']: 30,
|
||||
['__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__']: "",
|
||||
};
|
||||
|
||||
const keysOnly = Object.keys(environmentVariables);
|
||||
|
||||
module.exports = {
|
||||
environmentVariablesWithoutDefaults: keysOnly,
|
||||
environmentVariablesWithDefaults: environmentVariables,
|
||||
};
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
const { environmentVariablesWithDefaults } = require('./environment-variables.js');
|
||||
|
||||
module.exports = {
|
||||
verbose: true,
|
||||
coverageReporters: ["html", "text", "jest-junit", "cobertura"], reporters: ['default', 'jest-junit'],
|
||||
|
|
@ -49,3 +51,5 @@ module.exports = {
|
|||
// Uncomment this to avoid the massive amount of warnings we are getting for onSubmit and onInvalidSubmit
|
||||
//silent: true,
|
||||
};
|
||||
|
||||
process.env = Object.assign(process.env, environmentVariablesWithDefaults);
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
<script>
|
||||
window.dataLayer = [{}];
|
||||
</script>
|
||||
<script><%= process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY %></script>
|
||||
<script><%= process.env.__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__ %></script>
|
||||
<script src="https://applepay.cdn-apple.com/jsapi/v1.1.0/apple-pay-sdk.js"></script>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
<!-- Google Tag Manager -->
|
||||
<noscript>
|
||||
<iframe src="<%= process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC %>"
|
||||
<iframe src="<%= process.env.__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__ %>"
|
||||
height="0" width="0" style="display:none;visibility:hidden"></iframe>
|
||||
</noscript>
|
||||
|
||||
|
|
@ -27,6 +27,6 @@
|
|||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
|
||||
<%= process.env.VUE_APP_SOLARWINDS_MONITORING_SCRIPT %>
|
||||
<%= process.env.__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__ %>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
const applicationConfig = {
|
||||
CONSUMER_CF_DISTRO: process.env.VUE_APP_CONSUMER_CF_DISTRO,
|
||||
GOOGLE_PLACES_API_KEY: process.env.VUE_APP_GOOGLE_PLACES_API_KEY,
|
||||
CONSUMER_CF_DISTRO: process.env.__VUE_APP_CONSUMER_CF_DISTRO__,
|
||||
GOOGLE_PLACES_API_KEY: process.env.__VUE_APP_GOOGLE_PLACES_API_KEY__,
|
||||
ANALYTICS_SESSION_TIMEOUT_MINUTES: 30,
|
||||
SAVED_SESSION_TIMEOUT_DAYS: 45,
|
||||
COOKIE_PATH: "/",
|
||||
CURRENT_ENVIRONMENT: process.env.VUE_APP_CURRENT_ENVIRONMENT, // "Localhost", "Dev", "QA", and "Prod"
|
||||
HERITAGE_FUNNEL: process.env.VUE_APP_HERITAGE_FUNNEL,
|
||||
SAFELITE_HOP: process.env.VUE_APP_SAFELITE_HOP,
|
||||
CURRENT_ENVIRONMENT: process.env.__VUE_APP_CURRENT_ENVIRONMENT__, // "Localhost", "Dev", "QA", and "Prod"
|
||||
HERITAGE_FUNNEL: process.env.__VUE_APP_HERITAGE_FUNNEL__,
|
||||
SAFELITE_HOP: process.env.__VUE_APP_SAFELITE_HOP__,
|
||||
APPLICATION_NAME: "FixMyGlass",
|
||||
ANALYTICS_APPLICATION_NAME: "FixMyGlassNextGen",
|
||||
APPLICATION_ABBREVIATION: "fmg",
|
||||
|
|
@ -14,7 +14,7 @@ const applicationConfig = {
|
|||
SITE_ENTRY_TRIGGER_VALUE: "FixMyGlass",
|
||||
CASH_PARENT_ACCOUNT_NUMBER: 167132,
|
||||
CASH_DEFAULT_BILL_TO_ACCOUNT_NUMBER: "87291",
|
||||
MY_ACCOUNT: process.env.VUE_APP_MY_ACCOUNT,
|
||||
MY_ACCOUNT: process.env.__VUE_APP_MY_ACCOUNT__,
|
||||
PIA_RESPONSE_URL:
|
||||
location.protocol + "//" + location.host + "/fmg/payment-pia-return?src=concept-funnel",
|
||||
PIA_CANCEL_URL:
|
||||
|
|
@ -29,7 +29,7 @@ const applicationConfig = {
|
|||
FRONTEND_LOGGER_PATH: "/analytics/api/v1/logging",
|
||||
AFFILIATE_COOKIE_CONTAINING_NAME: "_Track",
|
||||
COOKIE_NAME_LENGTH_MAX_LIMIT: 44,
|
||||
SESSION_TIMEOUT_MINUTES: process.env.VUE_APP_SESSION_TIMEOUT_MINUTES,
|
||||
SESSION_TIMEOUT_MINUTES: process.env.__VUE_APP_SESSION_TIMEOUT_MINUTES__,
|
||||
RETURN_USER_PAGE: "/fmg/return-user",
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -2,16 +2,6 @@
|
|||
<div
|
||||
class="date-picker text-center"
|
||||
:class="`${calendarViewDirection} calendar-2025 ${showPricingByDayClass}`">
|
||||
<div class="date-picker-header">
|
||||
<funnelSubHeader cmsWidgetName="DatePickerSubHeaderWidget" class="mt-5" />
|
||||
<textBlock
|
||||
v-show="durationTextBlockCopy"
|
||||
:customText="durationTextBlockCopy"
|
||||
typeStyle="small"
|
||||
marginTopSizeOverride="0"
|
||||
class="duration-text-block" />
|
||||
</div>
|
||||
|
||||
<fieldset id="date-picker-fieldset" ref="datePickerFieldset">
|
||||
<legend class="sr-only">Select a day and time</legend>
|
||||
<div
|
||||
|
|
@ -139,36 +129,11 @@
|
|||
@click="showAnotherMonth">
|
||||
View more dates
|
||||
</button>
|
||||
<timeSlotQuestion
|
||||
ref="timeSlotModalQuestion"
|
||||
v-model="selectedTimeSlotInfo"
|
||||
cmsWidgetName="TimeSlotModalQuestion"
|
||||
waitListLabelWidget="WaitListLabelWidget"
|
||||
waitListQuestionWidget="WaitListQuestionWidget"
|
||||
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
||||
mobileCmsWidgetName="MobileTimeSlotModal"
|
||||
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
||||
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
||||
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
||||
dropOffOrPickATimeQuestionCmsWidgetName="DropOffOrPickATimeQuestionWidget"
|
||||
:selectedDate="selectedDate"
|
||||
:appointmentType="appointmentType"
|
||||
:premiumAppointmentFee="premiumAppointmentFee"
|
||||
:displayWaitList="displayWaitList"
|
||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||
:estimatedServiceMinutesMinimum="estimatedServiceMinutesMinimum"
|
||||
:estimatedServiceMinutesMaximum="estimatedServiceMinutesMaximum"
|
||||
@waitListRequested="handleWaitListRequested"
|
||||
@time-slot-modal-closed="timeSlotModalClosed" />
|
||||
</fieldset>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import timeSlotQuestion from "@/layouts/schedule/time-slot-question/time-slot-question.vue";
|
||||
import textBlock from "@/digital-components/text-block/text-block";
|
||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||
|
||||
// Supporting files
|
||||
import loader from "@/ux-components/loader/loader";
|
||||
import store from "@/store";
|
||||
|
|
@ -178,12 +143,6 @@ import {
|
|||
MONTHS_OF_YEAR,
|
||||
DAYS_OF_WEEK,
|
||||
} from "@/digital-components/date-picker/mixins/constants";
|
||||
import {
|
||||
AppointmentTypeStrings,
|
||||
RouteCodeFlags,
|
||||
PREMIUM_FEE_PART_TYPE,
|
||||
cmsWidgetFieldMappings,
|
||||
} from "@/constants/schedule-constants";
|
||||
import {
|
||||
selectableDaysOptions,
|
||||
requiredParameter,
|
||||
|
|
@ -195,7 +154,6 @@ import {
|
|||
import { useField, ErrorMessage } from "vee-validate";
|
||||
import { deepClone } from "@/helpers/object-helper";
|
||||
import { v4 as uuidv4 } from "uuid";
|
||||
import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helper";
|
||||
|
||||
export default {
|
||||
name: "datePicker",
|
||||
|
|
@ -205,10 +163,8 @@ export default {
|
|||
months: null,
|
||||
disableViewMoreDatesButton: false,
|
||||
hideSomeDaysForInitialView: null,
|
||||
selectedTimeSlotInfo: this.getSelectedTimeSlotInfo(),
|
||||
selectableDatesInshop: [], // NOTE: this and the mobile version below use monthNum (1-based), NOT monthIndex (0-based)
|
||||
selectableDatesMobile: [],
|
||||
durationTextBlockCopyForInshopOrDropoff: null,
|
||||
};
|
||||
},
|
||||
props: {
|
||||
|
|
@ -242,12 +198,6 @@ export default {
|
|||
pricingByDayBasePrice: Number,
|
||||
pricingByDayUpcharge: Number,
|
||||
isPricingByDayExperiment: Boolean,
|
||||
timeSlotsForSelectedDate: Object,
|
||||
appointmentType: String,
|
||||
premiumAppointmentFee: Object,
|
||||
estimatedServiceMinutesMinimum: Number,
|
||||
estimatedServiceMinutesMaximum: Number,
|
||||
displayWaitList: Boolean,
|
||||
isMobileSelected: Boolean,
|
||||
},
|
||||
setup(props) {
|
||||
|
|
@ -309,80 +259,10 @@ export default {
|
|||
this.dispatchStoreAction(this.storeActions.SAVE_WAITLIST_REQUESTED, false, false);
|
||||
},
|
||||
},
|
||||
dropOffDurationText() {
|
||||
return this.getCmsContent("DropOffTimeSlotModal", cmsWidgetFieldMappings.DURATION);
|
||||
},
|
||||
sameDayDropoffDurationText() {
|
||||
return this.getCmsContent(
|
||||
"SameDayDropOffTimeSlotModal",
|
||||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
},
|
||||
overnightDropoffDurationText() {
|
||||
return this.getCmsContent(
|
||||
"OvernightDropOffTimeSlotModal",
|
||||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
},
|
||||
inshopDurationText() {
|
||||
const inshopDurationTextWithoutTime = this.getCmsContent(
|
||||
"TimeSlotModalQuestion",
|
||||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
|
||||
const inshopDurationTime = getDisplayTextForDurationLength(
|
||||
this.estimatedServiceMinutesMinimum,
|
||||
this.estimatedServiceMinutesMaximum
|
||||
);
|
||||
|
||||
if (this.estimatedServiceMinutesMinimum && this.estimatedServiceMinutesMaximum) {
|
||||
return `${inshopDurationTextWithoutTime} <b>${inshopDurationTime}</b>`;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
mobileDurationText() {
|
||||
const mobileDurationTextWithoutTime = this.getCmsContent(
|
||||
"TimeSlotModalQuestion",
|
||||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
|
||||
const mobileDurationTime = getDisplayTextForDurationLength(
|
||||
this.estimatedServiceMinutesMinimum,
|
||||
this.estimatedServiceMinutesMaximum
|
||||
);
|
||||
|
||||
if (this.estimatedServiceMinutesMinimum && this.estimatedServiceMinutesMaximum) {
|
||||
return `${mobileDurationTextWithoutTime} <b>${mobileDurationTime}</b>`;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
durationTextBlockCopy() {
|
||||
if (this.appointmentType === AppointmentTypeStrings.MOBILE) {
|
||||
return this.mobileDurationText;
|
||||
} else if (this.appointmentType === AppointmentTypeStrings.IN_SHOP) {
|
||||
return this.inshopDurationText;
|
||||
} else if (
|
||||
this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF ||
|
||||
this.appointmentType === AppointmentTypeStrings.DROP_OFF
|
||||
) {
|
||||
return this.durationTextBlockCopyForInshopOrDropoff ?? this.inshopDurationText;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
isSameDay() {
|
||||
if (!this.timeSlotsForSelectedDate) {
|
||||
return false;
|
||||
}
|
||||
const todaysDate = new Date().toISOString().split("T")[0];
|
||||
return this.selectedDate === todaysDate;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
async initializeComponent(initialData) {
|
||||
await this.setCalendarData(initialData);
|
||||
this.$refs.timeSlotModalQuestion.initializeComponent();
|
||||
},
|
||||
fireDateSelectedEvent(event, date) {
|
||||
// Ignore if arrow key selected radioButton
|
||||
|
|
@ -949,42 +829,9 @@ export default {
|
|||
};
|
||||
window.requestAnimationFrame(step);
|
||||
},
|
||||
getSelectedTimeSlotInfo() {
|
||||
const supportingItems = this.getSupportingItems();
|
||||
|
||||
var isPremiumAppointment = false;
|
||||
if (supportingItems) {
|
||||
isPremiumAppointment =
|
||||
!!supportingItems.filter(
|
||||
(lineItem) => lineItem.partType === PREMIUM_FEE_PART_TYPE
|
||||
).length > 0;
|
||||
}
|
||||
|
||||
const selectedTimeSlotInfo = {
|
||||
timeSlot: store.getters.order.schedule,
|
||||
isPremiumAppointment: isPremiumAppointment,
|
||||
};
|
||||
|
||||
return selectedTimeSlotInfo;
|
||||
},
|
||||
getSupportingItems() {
|
||||
return store.getters.lineItems.supportingItems;
|
||||
},
|
||||
handleWaitListRequested(value) {
|
||||
this.$emit("waitListRequested", value);
|
||||
},
|
||||
getDurationTextBlockCopyForInshopOrDropoff(selectedRouteCode) {
|
||||
if (selectedRouteCode?.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) {
|
||||
return this.overnightDropoffDurationText;
|
||||
} else if (selectedRouteCode?.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) {
|
||||
if (this.isSameDay) {
|
||||
return this.sameDayDropoffDurationText;
|
||||
} else {
|
||||
return this.dropOffDurationText;
|
||||
}
|
||||
}
|
||||
return this.inshopDurationText;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue(newValue) {
|
||||
|
|
@ -998,19 +845,10 @@ export default {
|
|||
this.scrollToElement("date-of-month-error");
|
||||
}
|
||||
},
|
||||
selectedTimeSlotInfo(newValue) {
|
||||
const routeCode = newValue?.timeSlot?.routeCode;
|
||||
this.durationTextBlockCopyForInshopOrDropoff =
|
||||
this.getDurationTextBlockCopyForInshopOrDropoff(routeCode);
|
||||
this.$emit("TimeSlotSelected", newValue); // needed to update footer button text on Schedule page and to save to Store correctly
|
||||
},
|
||||
},
|
||||
components: {
|
||||
loader,
|
||||
ErrorMessage,
|
||||
timeSlotQuestion,
|
||||
textBlock,
|
||||
funnelSubHeader,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1028,14 +866,6 @@ export default {
|
|||
align-items: flex-start;
|
||||
text-align: left;
|
||||
|
||||
.duration-text-block {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.date-picker-header {
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
flex-grow: 1;
|
||||
position: relative;
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
]"
|
||||
:validationRules="validationRules"
|
||||
@change="handleChange"
|
||||
@blur="handleChange"
|
||||
@blur="handleBlur"
|
||||
:maxlength="maxLength ? maxLength : '999'"
|
||||
@focus="$emit('focus', $event.target.value)"
|
||||
@keydown="keyDownHandler"
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ export default {
|
|||
name: "cart",
|
||||
props: {
|
||||
modelValue: Object,
|
||||
inactivePromos: Object,
|
||||
damage: Object,
|
||||
servicePackageOptionsCmsName: String,
|
||||
availableVaps: Object,
|
||||
|
|
@ -327,15 +328,26 @@ export default {
|
|||
this.lineItems.vaps = [...lineItems.vaps];
|
||||
this.lineItems.promos = [...lineItems.promos];
|
||||
await this.dispatchStoreAction(storeActions.SAVE_VAPS, this.lineItems.vaps, false);
|
||||
|
||||
// any new promos that are also in inactive list?
|
||||
const newInactivePromos = this.inactivePromos.filter((promo) => {
|
||||
return this.lineItems.promos.includes(promo);
|
||||
});
|
||||
this.updateInactivePromos(newInactivePromos);
|
||||
|
||||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
|
||||
{
|
||||
activePromos: this.lineItems.promos,
|
||||
inactivePromos: this.inactivePromos,
|
||||
},
|
||||
false
|
||||
);
|
||||
},
|
||||
|
||||
updateInactivePromos(newInactivePromos) {
|
||||
this.$emit("update:inactivePromos", newInactivePromos);
|
||||
},
|
||||
getPromoCodeList() {
|
||||
if (this.$refs["promoModalQuestion"]) {
|
||||
return this.$refs["promoModalQuestion"].getPromoCodeList();
|
||||
|
|
|
|||
|
|
@ -42,12 +42,12 @@ export async function navigateToHeritageFunnel({ shouldSaveSession, pageNameToLo
|
|||
}
|
||||
|
||||
if (
|
||||
(process.env.VUE_APP_HERITAGE_FUNNEL.includes("fixmyglasstest") &&
|
||||
process.env.VUE_APP_CURRENT_ENVIRONMENT === "Localhost") ||
|
||||
(process.env.VUE_APP_HERITAGE_FUNNEL.includes("fixmyglassdev") &&
|
||||
process.env.VUE_APP_CURRENT_ENVIRONMENT === "Localhost") ||
|
||||
(process.env.VUE_APP_HERITAGE_FUNNEL.includes("localhost") &&
|
||||
process.env.VUE_APP_CURRENT_ENVIRONMENT === "Localhost")
|
||||
(applicationConfig.HERITAGE_FUNNEL.includes("fixmyglasstest") &&
|
||||
applicationConfig.CURRENT_ENVIRONMENT === "Localhost") ||
|
||||
(applicationConfig.HERITAGE_FUNNEL.includes("fixmyglassdev") &&
|
||||
applicationConfig.CURRENT_ENVIRONMENT === "Localhost") ||
|
||||
(applicationConfig.HERITAGE_FUNNEL.includes("localhost") &&
|
||||
applicationConfig.CURRENT_ENVIRONMENT === "Localhost")
|
||||
) {
|
||||
heritageParms["forceEndToEndInsurance"] = true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -275,6 +275,7 @@ export default {
|
|||
}
|
||||
.sub-text strong {
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,15 @@ import { shallowMount } from "@vue/test-utils";
|
|||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||
import store from "@/store";
|
||||
import { experimentSettings } from "@/constants/experiments";
|
||||
import { storeMutations } from "@/constants/store-mutations";
|
||||
import globalMethods from "@/global-methods";
|
||||
|
||||
globalMethods.callHttpClient = jest.fn();
|
||||
|
||||
global.crypto = { randomUUID: jest.fn() };
|
||||
const mockPriceOrderItemsAndSaveServerData = jest
|
||||
.fn()
|
||||
.mockResolvedValue(/* your mock return value */);
|
||||
|
||||
// Mock our module for promises.
|
||||
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||
|
|
@ -34,7 +43,6 @@ describe("payment-method.vue", () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithoutSaving).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test("if the continue button is clicked, navigate forward", async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks();
|
||||
|
|
@ -81,7 +89,10 @@ function setupMocks() {
|
|||
city: "Anytown",
|
||||
state: "OH",
|
||||
zipCode: "00000",
|
||||
provider: { providerNumber: "0000567" },
|
||||
},
|
||||
vehicle: { year: 2020, make: "Toyota", model: "Camry", carId: "12345" },
|
||||
damage: { isRepair: false },
|
||||
},
|
||||
policy: {
|
||||
currentDeductible: 123,
|
||||
|
|
@ -101,6 +112,9 @@ function setupMocks() {
|
|||
store: {
|
||||
getters: store.getters,
|
||||
},
|
||||
actions: {
|
||||
priceOrderItemsAndSaveServerData: mockPriceOrderItemsAndSaveServerData,
|
||||
},
|
||||
});
|
||||
|
||||
const mockMixin = {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
:availableVaps="availableVaps"
|
||||
:allowItemRemoval="true"
|
||||
v-model="lineItems"
|
||||
v-model:inactivePromos="inactivePromos"
|
||||
pageName="payment-method"
|
||||
servicePackageOptionsCmsName="ServicePackageTitle"
|
||||
recyclingModalCmsWidgetName="RecycleModal"
|
||||
|
|
@ -263,7 +264,7 @@ export default {
|
|||
: (resultMap.wipers.filter((wiper) => wiper.partType == partTypeStrings.REAR_WIPER) ??
|
||||
[]);
|
||||
|
||||
const lineItemsToTax = [
|
||||
const allLineItems = [
|
||||
resultMap.rainDefense,
|
||||
...supportingItems,
|
||||
...availableFrontWipers,
|
||||
|
|
@ -272,6 +273,10 @@ export default {
|
|||
...vaps,
|
||||
];
|
||||
|
||||
const lineItemsToTax = Array.from(
|
||||
new Map(allLineItems.map((item) => [item.partNumber, item])).values()
|
||||
);
|
||||
|
||||
const availableVaps = [
|
||||
resultMap.rainDefense,
|
||||
...availableFrontWipers,
|
||||
|
|
@ -542,6 +547,16 @@ export default {
|
|||
getPromoCodeWithoutBundleIdentifier(x.promoCode)
|
||||
);
|
||||
|
||||
// SAVE PROMO CHANGES TO STORE
|
||||
this.dispatchStoreAction(
|
||||
storeActions.SAVE_ACTIVE_AND_OR_INACTIVE_PROMOS,
|
||||
{
|
||||
activePromos: this.lineItems.promos,
|
||||
inactivePromos: this.inactivePromos,
|
||||
},
|
||||
false
|
||||
);
|
||||
|
||||
this.$refs.loadingModal.hideModal();
|
||||
},
|
||||
getIsRecalAckOptInFromStore() {
|
||||
|
|
@ -563,6 +578,7 @@ export default {
|
|||
this.paymentMethod,
|
||||
false
|
||||
);
|
||||
|
||||
// save lineitems as they now have salestax added
|
||||
await this.dispatchStoreAction(
|
||||
storeActions.SAVE_GLASS_PARTS_SUPPRESSING_STATE_RESETTING,
|
||||
|
|
@ -820,7 +836,7 @@ export default {
|
|||
isAfterpayBreakoutDisplay() {
|
||||
return (
|
||||
this.showInsuranceCoverageAs !== coverageStatus.PENDING &&
|
||||
(!this.isRecalPriceRemove || !this.isRecalibrationOnOrder) &&
|
||||
!this.isRecalPriceRemove &&
|
||||
this.hasSettingEqualTo(experimentSettings.DISPLAY_AFTERPAY_BREAKOUT_DISPLAY, "true")
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||
<loadingModal ref="loadingModal" />
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||
<div class="container quote position-relative">
|
||||
<div
|
||||
class="container quote position-relative"
|
||||
:class="[showSaveProgressPopup ? 'initial-popup-open' : '']">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-12">
|
||||
<funnelSubHeader class="mb-5" cmsWidgetName="FunnelSubHeaderWidget" />
|
||||
|
|
@ -286,6 +288,7 @@ export default {
|
|||
const isEmailInStoreOnPageLoad = emailFromStore?.length > 0;
|
||||
const isPopupSkipped =
|
||||
store.getters.pageData(routeData.QUOTE.name)?.saveProgressPopupSkipped === true;
|
||||
// "popup" is the automatic opening centered popup on load
|
||||
const showSaveProgressPopup = !(isEmailInStoreOnPageLoad || isPopupSkipped);
|
||||
const showSaveProgressModal = isEmailInStoreOnPageLoad ? false : true;
|
||||
const shouldSkipToInsurance =
|
||||
|
|
@ -555,8 +558,8 @@ export default {
|
|||
servicePackage: null,
|
||||
holdParentAccountNumber: null,
|
||||
holdBillToAccountNumber: null,
|
||||
showSaveProgressPopup: null,
|
||||
showSaveProgressModal: null,
|
||||
showSaveProgressPopup: null, // "popup" is the automatic opening centered popup on load
|
||||
showSaveProgressModal: null, // "modal" is the user-triggered slide-in drawer
|
||||
isSaveProgressComplete: null,
|
||||
packageNumber: null,
|
||||
skipToInsurance: null,
|
||||
|
|
@ -899,6 +902,10 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
// Unique to quote page for 2.0/Heritage parity
|
||||
// prettier-ignore
|
||||
.prevent-modal-scroll.modal-open .container.quote.initial-popup-open .row:not(.save-progress-popup) {
|
||||
display: none;
|
||||
}
|
||||
.quote {
|
||||
padding-bottom: 2rem;
|
||||
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ export default {
|
|||
},
|
||||
isAfterpayBreakoutDisplay() {
|
||||
return (
|
||||
(!this.shouldHideRecalibration || !this.isRecalibrationOnOrder) &&
|
||||
!this.shouldHideRecalibration &&
|
||||
experimentMixin.methods.hasSettingEqualTo(
|
||||
experimentSettings.DISPLAY_AFTERPAY_BREAKOUT_DISPLAY,
|
||||
"true"
|
||||
|
|
|
|||
114
src/layouts/schedule/duration-text-block/duration-text-block.vue
Normal file
114
src/layouts/schedule/duration-text-block/duration-text-block.vue
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
<template>
|
||||
<textBlock
|
||||
:customText="durationTextBlockCopy"
|
||||
typeStyle="small"
|
||||
marginTopSizeOverride="0"
|
||||
class="duration-text-block" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import textBlock from "@/digital-components/text-block/text-block";
|
||||
|
||||
// Constants
|
||||
import { AppointmentTypeStrings, cmsWidgetFieldMappings } from "@/constants/schedule-constants";
|
||||
|
||||
// Helpers
|
||||
import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helper";
|
||||
|
||||
export default {
|
||||
name: "duration-text-block",
|
||||
props: {
|
||||
isSameDay: Boolean,
|
||||
appointmentType: String,
|
||||
estimatedServiceMinutesMinimum: String,
|
||||
estimatedServiceMinutesMaximum: String,
|
||||
isOvernightDropoff: Boolean,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedRouteCode: null,
|
||||
selectedAnswerForDropOffOrInshop: null,
|
||||
selectedAnswerForTimeSlots: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
dropOffDurationText() {
|
||||
return this.getCmsContent("DropOffTimeSlotModal", cmsWidgetFieldMappings.DURATION);
|
||||
},
|
||||
sameDayDropoffDurationText() {
|
||||
return this.getCmsContent(
|
||||
"SameDayDropOffTimeSlotModal",
|
||||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
},
|
||||
overnightDropoffDurationText() {
|
||||
return this.getCmsContent(
|
||||
"OvernightDropOffTimeSlotModal",
|
||||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
},
|
||||
inshopDurationText() {
|
||||
const inshopDurationTextWithoutTime = this.getCmsContent(
|
||||
"TimeSlotModalQuestion",
|
||||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
|
||||
const inshopDurationTime = getDisplayTextForDurationLength(
|
||||
this.estimatedServiceMinutesMinimum,
|
||||
this.estimatedServiceMinutesMaximum
|
||||
);
|
||||
|
||||
if (this.estimatedServiceMinutesMinimum && this.estimatedServiceMinutesMaximum) {
|
||||
return `${inshopDurationTextWithoutTime} <b>${inshopDurationTime}</b>`;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
mobileDurationText() {
|
||||
const mobileDurationTextWithoutTime = this.getCmsContent(
|
||||
"TimeSlotModalQuestion",
|
||||
cmsWidgetFieldMappings.DURATION
|
||||
);
|
||||
|
||||
const mobileDurationTime = getDisplayTextForDurationLength(
|
||||
this.estimatedServiceMinutesMinimum,
|
||||
this.estimatedServiceMinutesMaximum
|
||||
);
|
||||
|
||||
if (this.estimatedServiceMinutesMinimum && this.estimatedServiceMinutesMaximum) {
|
||||
return `${mobileDurationTextWithoutTime} ${mobileDurationTime}`;
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
durationTextBlockCopy() {
|
||||
if (this.appointmentType === AppointmentTypeStrings.MOBILE) {
|
||||
return this.mobileDurationText;
|
||||
} else if (this.appointmentType === AppointmentTypeStrings.DROP_OFF) {
|
||||
return this.getDurationTextBlockCopyForDropoff();
|
||||
} else {
|
||||
return this.inshopDurationText;
|
||||
}
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
getDurationTextBlockCopyForDropoff() {
|
||||
if (this.isOvernightDropoff) {
|
||||
return this.overnightDropoffDurationText;
|
||||
} else {
|
||||
if (this.isSameDay) {
|
||||
return this.sameDayDropoffDurationText;
|
||||
} else {
|
||||
return this.dropOffDurationText;
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
textBlock,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style></style>
|
||||
|
|
@ -0,0 +1,141 @@
|
|||
<template>
|
||||
<div
|
||||
class="mobile-fee-waiver-alert-container py-3 px-4 my-2"
|
||||
:class="[isExpanded ? 'expanded' : '']">
|
||||
<div
|
||||
class="mobile-fee-waiver-header d-flex align-items-center justify-content-between"
|
||||
@click="toggleIsExpanded">
|
||||
<span>
|
||||
{{ headerText }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="mobile-fee-waiver-body">
|
||||
<div class="mobile-fee-waiver-copy">
|
||||
{{ subheaderText }}
|
||||
</div>
|
||||
<div class="mobile-fee-waiver-price-comp">
|
||||
<span class="mobile-fee-waiver-strikethrough-price">
|
||||
{{ priceStrikethroughText }}
|
||||
</span>
|
||||
<span class="mobile-fee-waiver-free-price">{{ freePriceText }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "mobile-fee-waiver-alert",
|
||||
props: {
|
||||
cmsWidgetName: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isExpanded: true,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
headerText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "HeaderText");
|
||||
},
|
||||
subheaderText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
|
||||
},
|
||||
priceStrikethroughText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "FooterText");
|
||||
},
|
||||
freePriceText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, "FooterText2");
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
toggleIsExpanded() {
|
||||
this.setIsExpanded(!this.isExpanded);
|
||||
},
|
||||
setIsExpanded(newVal) {
|
||||
this.isExpanded = newVal;
|
||||
},
|
||||
},
|
||||
components: {},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.mobile-fee-waiver-alert-container {
|
||||
background: $green-100;
|
||||
border-radius: 0.25em;
|
||||
border: 1px solid $green-400;
|
||||
|
||||
.mobile-fee-waiver-header {
|
||||
font-weight: bold;
|
||||
|
||||
span {
|
||||
flex-grow: 1;
|
||||
color: $black;
|
||||
}
|
||||
|
||||
&::before {
|
||||
content: "";
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 16'%3E%3Cpath fill='%230C7E47' d='M8 0a8 8 0 1 0 0 16A8 8 0 0 0 8 0Zm3.7 6.171-4.449 4.45a.559.559 0 0 1-.8 0l-2.16-2.16a.563.563 0 0 1 .792-.8l1.76 1.76 4.066-4.042a.563.563 0 1 1 .792.8v-.008Z'/%3E%3C/svg%3E");
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
display: inline-block;
|
||||
margin-right: 0.5rem;
|
||||
}
|
||||
|
||||
&::after {
|
||||
content: "";
|
||||
transition: all 0.5s ease;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 16 9'%3E%3Cpath d='M7.99282 0.117702C7.75716 0.116049 7.53044 0.207797 7.3623 0.37286L0.255553 7.46878C0.0862976 7.63796 -0.00878906 7.86742 -0.00878906 8.10667C-0.00878906 8.34593 0.0862976 8.57539 0.255553 8.74457C0.424808 8.91374 0.654368 9.00879 0.893731 9.00879C1.13309 9.00879 1.36265 8.91374 1.53191 8.74457L7.99282 2.27378L14.4614 8.74457C14.6307 8.91205 14.8595 9.00547 15.0977 9.00428C15.3359 9.00308 15.5638 8.90737 15.7314 8.73819C15.8989 8.56901 15.9924 8.34022 15.9912 8.10216C15.99 7.8641 15.8942 7.63627 15.725 7.46878L8.6259 0.377963C8.45765 0.21088 8.22999 0.117289 7.99282 0.117702Z' fill='%230C7E47'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center center;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-fee-waiver-body {
|
||||
transition: all 500ms ease-out;
|
||||
visibility: hidden;
|
||||
overflow: hidden;
|
||||
max-height: 0;
|
||||
|
||||
.mobile-fee-waiver-price-comp {
|
||||
margin-top: 0.5em;
|
||||
|
||||
.mobile-fee-waiver-strikethrough-price {
|
||||
font-size: smaller;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.mobile-fee-waiver-free-price {
|
||||
display: inline-block;
|
||||
font-weight: bolder;
|
||||
border-radius: 1em;
|
||||
background-color: $green-300;
|
||||
padding: 0 0.5em;
|
||||
margin-inline-start: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.expanded {
|
||||
.mobile-fee-waiver-header {
|
||||
&::after {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-fee-waiver-body {
|
||||
visibility: visible;
|
||||
max-height: none;
|
||||
|
||||
border-top: 1px solid $green-400;
|
||||
padding-top: 0.5em;
|
||||
margin-top: 0.5em;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -5,17 +5,16 @@
|
|||
<div class="container page-container-grouped-styles">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<alert
|
||||
ref="alertMobileFeeFree"
|
||||
class="mb-5"
|
||||
cmsWidgetName="AlertMobileFeeFreeWidget"
|
||||
v-if="showMobileFreeAlert"
|
||||
alertClass="alert-success" />
|
||||
<mobileFeeWaiverAlert
|
||||
cmsWidgetName="MobileFeeFreeDropdownWidget"
|
||||
v-if="showMobileFreeAlert" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row appointment-type">
|
||||
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<funnelSubHeader cmsWidgetName="ScheduleYourServiceWidget" class="mb-5" />
|
||||
<funnelSubHeader
|
||||
cmsWidgetName="ScheduleYourServiceWidget"
|
||||
id="schedule-your-service" />
|
||||
<appointmentTypeQuestion
|
||||
v-model="appointmentTypeFromAppointmentTypeQuestion"
|
||||
v-show="isAppointmentTypeDisplayed"
|
||||
|
|
@ -118,6 +117,15 @@
|
|||
<div class="row date-picker-wrapper">
|
||||
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<locationAlerts cmsWidgetPrefix="LocationAlert-" ref="locationAlerts" />
|
||||
<div v-show="appointmentType" class="date-picker-header fw-normal mt-5 mb-5">
|
||||
<textBlock :customText="datePickerHeaderText" typeStyle="button-question" />
|
||||
<durationTextBlock
|
||||
:isSameDay="isSameDay"
|
||||
:appointmentType="appointmentType"
|
||||
:estimatedServiceMinutesMinimum="estimatedServiceMinutesMinimum"
|
||||
:estimatedServiceMinutesMaximum="estimatedServiceMinutesMaximum"
|
||||
:isOvernightDropoff="isOvernightDropoff" />
|
||||
</div>
|
||||
<datePicker
|
||||
:currentZip="zipCode"
|
||||
:currentProviderNumber="selectedProvider?.providerNumber"
|
||||
|
|
@ -134,14 +142,25 @@
|
|||
:pricingByDayBasePrice="pricingByDayBasePrice"
|
||||
:pricingByDayUpcharge="pricingByDayUpcharge"
|
||||
:showPricingByDay="showPricingByDay"
|
||||
:isPricingByDayExperiment="isPricingByDayExperiment"
|
||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||
:isPricingByDayExperiment="isPricingByDayExperiment" />
|
||||
<timeSlotQuestion
|
||||
ref="timeSlotModalQuestion"
|
||||
v-if="showTimeSlotQuestion"
|
||||
@time-slot-selection-changed="updateTimeSlot"
|
||||
waitListLabelWidget="WaitListLabelWidget"
|
||||
waitListQuestionWidget="WaitListQuestionWidget"
|
||||
mobilePremiumCmsWidgetName="MobilePremiumTimeSlotModal"
|
||||
mobileCmsWidgetName="MobileTimeSlotModal"
|
||||
dropoffCmsWidgetName="DropOffTimeSlotModal"
|
||||
sameDayDropOffCmsWidgetName="SameDayDropOffTimeSlotModal"
|
||||
overnightDropOffCmsWidgetName="OvernightDropOffTimeSlotModal"
|
||||
dropOffOrPickATimeQuestionCmsWidgetName="DropOffOrPickATimeQuestionWidget"
|
||||
:appointmentType="appointmentType"
|
||||
:premiumAppointmentFee="mobilePremiumAppointmentFee"
|
||||
:estimatedServiceMinutesMinimum="getServiceMinutesMin"
|
||||
:estimatedServiceMinutesMaximum="getServiceMinutesMax"
|
||||
@timeSlotSelected="updateTimeSlot"
|
||||
:displayWaitList="displayWaitList"
|
||||
:timeSlotsForSelectedDate="timeSlotsForSelectedDate"
|
||||
:isSameDay="isSameDay"
|
||||
:selectedRouteCodeData="selectedRouteCodeData"
|
||||
@waitListRequested="handleWaitListRequested" />
|
||||
<navbar
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
|
|
@ -160,9 +179,14 @@
|
|||
import alert from "@/ux-components/alert/alert";
|
||||
import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question";
|
||||
import appointmentTypeQuestion from "@/layouts/service-location/appointment-type-question/appointment-type-question";
|
||||
import shopQuestion from "@/layouts/service-location/shop-question/shop-question";
|
||||
import shopListButton from "@/layouts/service-location/shop-question/shop-list-button/shop-list-button";
|
||||
import shopLocation from "@/layouts/schedule/shop-location/shop-location";
|
||||
import timeSlotQuestion from "@/layouts/schedule/time-slot-question/time-slot-question.vue";
|
||||
import durationTextBlock from "@/layouts/schedule/duration-text-block/duration-text-block.vue";
|
||||
|
||||
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 funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||
|
|
@ -174,6 +198,7 @@ import datePicker from "@/digital-components/date-picker/date-picker";
|
|||
import locationAlerts from "@/layouts/schedule/location-alerts/location-alerts";
|
||||
import contentGroupModal from "@/fmg-components/content-group-modal/content-group-modal";
|
||||
import textBlock from "@/digital-components/text-block/text-block";
|
||||
import mobileFeeWaiverAlert from "./mobile-fee-waiver-alert/mobile-fee-waiver-alert.vue";
|
||||
|
||||
// Supporting files
|
||||
import baseMixin from "@/mixins/base-mixin.js";
|
||||
|
|
@ -497,14 +522,14 @@ export default {
|
|||
);
|
||||
|
||||
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
|
||||
const zipCodeDataPromise = getZipCodeData(serviceZipCode);
|
||||
const zipCodeDataPromise = getZipCodeData(serviceZipCode, to.name);
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(
|
||||
serviceZipCode,
|
||||
null,
|
||||
"service-location"
|
||||
to.name
|
||||
);
|
||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode, "service-location");
|
||||
const shopProviderData = await getShopProviderData(serviceZipCode);
|
||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode, to.name);
|
||||
const shopProviderData = await getShopProviderData(serviceZipCode, to.name);
|
||||
const providerNumber = shopProviderData?.data?.shopProviders[0]?.providerNumber;
|
||||
|
||||
// Get pricingByDayUpcharge needed for Pricing By Day
|
||||
|
|
@ -515,7 +540,7 @@ export default {
|
|||
const premiumFeePromise = baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
storeActions.GET_MOBILE_PREMIUM_FEE,
|
||||
null,
|
||||
"schedule"
|
||||
to.name
|
||||
);
|
||||
const premiumFeeWithPricePromise = premiumFeePromise.then((result) => {
|
||||
if (result.data) {
|
||||
|
|
@ -524,7 +549,7 @@ export default {
|
|||
{
|
||||
availableLineItems: [result.data],
|
||||
},
|
||||
"schedule",
|
||||
to.name,
|
||||
false
|
||||
);
|
||||
} else {
|
||||
|
|
@ -626,6 +651,16 @@ export default {
|
|||
return this.isGlassServiceableMobile;
|
||||
}
|
||||
},
|
||||
showTimeSlotQuestion() {
|
||||
if (
|
||||
this.selectedDate &&
|
||||
this.selectedDate.includes("mobile") &&
|
||||
!this.isMobileSelected
|
||||
) {
|
||||
this.getNewSelectedDate();
|
||||
}
|
||||
return this.selectedDate && this.appointmentTypeFromAppointmentTypeQuestion;
|
||||
},
|
||||
isMobileStaticRecalibrationApplicable() {
|
||||
return (
|
||||
this.displayMSR &&
|
||||
|
|
@ -785,6 +820,21 @@ export default {
|
|||
}
|
||||
return [];
|
||||
},
|
||||
selectedRouteCodeData() {
|
||||
if (!this.selectedTimeSlotInfo?.timeSlot?.routeCode) {
|
||||
return null;
|
||||
}
|
||||
return {
|
||||
routeCode: this.selectedTimeSlotInfo.timeSlot.routeCode,
|
||||
isPremiumAppointment: this.selectedTimeSlotInfo.isPremiumAppointment,
|
||||
};
|
||||
},
|
||||
questionText() {
|
||||
return this.getCmsContent("YourSafeliteShopWidget", "QuestionText");
|
||||
},
|
||||
datePickerHeaderText() {
|
||||
return this.getCmsContent("DatePickerSubHeaderWidget", "HeaderText");
|
||||
},
|
||||
appointmentTypeStrings() {
|
||||
return AppointmentTypeStrings;
|
||||
},
|
||||
|
|
@ -795,12 +845,12 @@ export default {
|
|||
// Splits content when brackets are found in text so that text can be looped through and router-link can be injected when needed
|
||||
return this.splitCopyOnCMSPlaceHolder(this.ChangeShopLinkText);
|
||||
},
|
||||
getServiceMinutesMin() {
|
||||
estimatedServiceMinutesMinimum() {
|
||||
return this.isMobileSelected
|
||||
? this.selectableDatesMobile.estimatedServiceMinutesMinimum
|
||||
: this.selectableDatesInshop.estimatedServiceMinutesMinimum;
|
||||
},
|
||||
getServiceMinutesMax() {
|
||||
estimatedServiceMinutesMaximum() {
|
||||
return this.isMobileSelected
|
||||
? this.selectableDatesMobile.estimatedServiceMinutesMaximum
|
||||
: this.selectableDatesInshop.estimatedServiceMinutesMaximum;
|
||||
|
|
@ -820,6 +870,18 @@ export default {
|
|||
);
|
||||
}
|
||||
},
|
||||
isSameDay() {
|
||||
const todaysDate = new Date().toISOString().split("T")[0];
|
||||
return this.selectedDate === todaysDate;
|
||||
},
|
||||
isOvernightDropoff() {
|
||||
return (
|
||||
this.selectedTimeSlotInfo?.timeSlot?.routeCode &&
|
||||
this.selectedTimeSlotInfo.timeSlot.routeCode.includes(
|
||||
RouteCodeFlags.OVERNIGHT_DROP_OFF
|
||||
)
|
||||
);
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
splitCopyOnCMSPlaceHolder,
|
||||
|
|
@ -1305,7 +1367,7 @@ export default {
|
|||
) {
|
||||
navigateToHeritageFunnel({
|
||||
shouldSaveSession: false,
|
||||
pageNameToLog: "service-location",
|
||||
pageNameToLog: this.pageName,
|
||||
navType: "back",
|
||||
});
|
||||
} else {
|
||||
|
|
@ -1558,22 +1620,46 @@ export default {
|
|||
}
|
||||
},
|
||||
updateTimeSlot(timeSlotObj) {
|
||||
if (this.preSelectedDate && !timeSlotObj?.timeSlot?.date) return;
|
||||
this.selectedTimeSlotInfo = timeSlotObj;
|
||||
if (!timeSlotObj?.routeCode) {
|
||||
this.appointmentType = AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF;
|
||||
this.selectedTimeSlotInfo = {
|
||||
timeSlot: {
|
||||
date: null,
|
||||
routeCode: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null,
|
||||
},
|
||||
isPremiumAppointment: null,
|
||||
};
|
||||
return;
|
||||
}
|
||||
const timeSlot = this.timeSlotsForSelectedDate?.timeSlots?.find(
|
||||
(slot) => slot.id == timeSlotObj.routeCode
|
||||
);
|
||||
|
||||
this.selectedTimeSlotInfo = {
|
||||
timeSlot: {
|
||||
date: this.timeSlotsForSelectedDate.date,
|
||||
routeCode: timeSlotObj.routeCode,
|
||||
startTime: timeSlot.startTime,
|
||||
endTime: timeSlot.endTime,
|
||||
jobMaxMinutes: this.estimatedServiceMinutesMaximum.toString(),
|
||||
jobMinMinutes: this.estimatedServiceMinutesMinimum.toString(),
|
||||
},
|
||||
isPremiumAppointment: timeSlotObj.isPremiumAppointment ? true : false,
|
||||
};
|
||||
|
||||
if (
|
||||
this.appointmentType !== AppointmentTypeStrings.MOBILE &&
|
||||
this.appointmentType !== null
|
||||
) {
|
||||
// update apptType based on routeCode to determine if it should be dropoff or inshop
|
||||
debugLog(`Updating appointment type based on route code.`);
|
||||
debugLog(`Route code =`, timeSlotObj.timeSlot.routeCode);
|
||||
debugLog(
|
||||
`Parsed type = `,
|
||||
this.getInShopOrDropOffApptType(timeSlotObj.timeSlot.routeCode)
|
||||
);
|
||||
this.appointmentType = this.getInShopOrDropOffApptType(
|
||||
timeSlotObj.timeSlot.routeCode
|
||||
);
|
||||
debugLog(`Route code =`, timeSlotObj.routeCode);
|
||||
debugLog(`Parsed type = `, this.getInShopOrDropOffApptType(timeSlotObj.routeCode));
|
||||
this.appointmentType = this.getInShopOrDropOffApptType(timeSlotObj.routeCode);
|
||||
}
|
||||
},
|
||||
getInShopOrDropOffApptType(routeCode) {
|
||||
|
|
@ -1607,8 +1693,13 @@ export default {
|
|||
},
|
||||
updateSelectedProvider(newProvider) {
|
||||
if (newProvider) {
|
||||
const didProviderNumberChange =
|
||||
this.selectedProvider.providerNumber !== newProvider.providerNumber;
|
||||
this.selectedProvider = newProvider;
|
||||
this.initializeDatePicker();
|
||||
|
||||
if (didProviderNumberChange) {
|
||||
this.initializeDatePicker();
|
||||
}
|
||||
} else if (this.appointmentType === this.appointmentTypeStrings.MOBILE) {
|
||||
this.selectedProvider = {
|
||||
providerNumber: this.shopProviderData.mobileProviderNumber.toString(),
|
||||
|
|
@ -1630,7 +1721,7 @@ export default {
|
|||
handleZipCodeChange(newZipCode) {
|
||||
this.resetMobileLocation();
|
||||
|
||||
getShopProviderData(newZipCode.zipCode).then((result) => {
|
||||
getShopProviderData(newZipCode.zipCode, this.pageName).then((result) => {
|
||||
this.shopProviderData = result.data;
|
||||
this.resetSelectedProvider();
|
||||
this.state = newZipCode.state;
|
||||
|
|
@ -1697,6 +1788,9 @@ export default {
|
|||
this.selectedDate = this.getSelectedDate();
|
||||
this.setDisplayWaitList();
|
||||
},
|
||||
getNewSelectedDate() {
|
||||
this.selectedDate = this.getSelectedDate();
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
appointmentTypeFromAppointmentTypeQuestion: {
|
||||
|
|
@ -1740,12 +1834,15 @@ export default {
|
|||
datePicker,
|
||||
locationAlerts,
|
||||
textBlock,
|
||||
timeSlotQuestion,
|
||||
|
||||
alert,
|
||||
serviceZipModalQuestion,
|
||||
appointmentTypeQuestion,
|
||||
contentGroupModal,
|
||||
durationTextBlock,
|
||||
shopLocation,
|
||||
mobileFeeWaiverAlert,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1780,12 +1877,17 @@ export default {
|
|||
font-weight: 600;
|
||||
}
|
||||
|
||||
:deep(.funnel-sub-header:not(.mb-5)) {
|
||||
:deep(.funnel-sub-header:not(#schedule-your-service)) {
|
||||
h5.dark-header {
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
:deep(.funnel-sub-header#schedule-your-service) {
|
||||
h5.dark-header {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.col-12 a {
|
||||
font-family: UrbanistSemibold;
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
<buttonQuestion
|
||||
v-if="isDropOffAppointmentAvailable"
|
||||
v-model="selectedAnswerForDropOffOrInshop"
|
||||
@update:modelValue="dropOffSelectionChanged"
|
||||
:questionText="dropOffOrPickATimeQuestionLabelText"
|
||||
:questionTextDescription="dropOffOrPickATimeQuestionDescription"
|
||||
:answers="answersForDropOffQuestion"
|
||||
|
|
@ -24,6 +25,7 @@
|
|||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-if="shouldDisplayTimeSlotQuestion"
|
||||
@update:modelValue="timeSlotSelectionChanged"
|
||||
buttonTypeString="timeSlotModalListButton"
|
||||
:buttonTypeObject="timeSlotModalListButton"
|
||||
class="mt-4 timeslots"
|
||||
|
|
@ -44,7 +46,7 @@
|
|||
v-if="supplementalInformationBlock"
|
||||
v-html="supplementalInformationBlock" />
|
||||
<div
|
||||
v-if="hasWaitListExperiment && displayWaitListFeature && selectedDate"
|
||||
v-if="hasWaitListExperiment && displayWaitListFeature"
|
||||
class="mt-5 bg-light rounded waitlist">
|
||||
<textBlock
|
||||
cmsWidgetName="WaitListLabelWidget"
|
||||
|
|
@ -59,7 +61,7 @@
|
|||
@click="waitListChecked" />
|
||||
</div>
|
||||
<div
|
||||
v-if="waitListRequested && displayWaitList && selectedDate"
|
||||
v-if="waitListRequested && displayWaitList"
|
||||
class="rounded waitlist-success"
|
||||
ref="waitlistSuccessMessage">
|
||||
<img :src="waitListSuccessImage" class="success-image" />
|
||||
|
|
@ -92,7 +94,6 @@ import {
|
|||
isDropOffRouteCode,
|
||||
militaryToTwelveHourTime,
|
||||
} from "@/layouts/schedule/helpers/schedule-helper";
|
||||
import { getDisplayTextForDurationLength } from "@/helpers/duration-length-helper";
|
||||
|
||||
// Validation
|
||||
import { defineRule, useField } from "vee-validate";
|
||||
|
|
@ -116,23 +117,8 @@ defineRule("time-slot-required", required(errorMessages.OPTION_REQUIRED));
|
|||
|
||||
export default {
|
||||
name: "time-slot-question",
|
||||
emits: ["update:modelValue", "TimeSlotSelected", "click-event"],
|
||||
emits: ["update:modelValue", "time-slot-selection-changed"],
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
timeSlot: {
|
||||
routeCode: null,
|
||||
date: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null,
|
||||
},
|
||||
isPremiumAppointment: null,
|
||||
}),
|
||||
},
|
||||
cmsWidgetName: String,
|
||||
mobileCmsWidgetName: String,
|
||||
mobilePremiumCmsWidgetName: String,
|
||||
dropoffCmsWidgetName: String,
|
||||
|
|
@ -142,21 +128,23 @@ export default {
|
|||
appointmentType: String,
|
||||
timeSlotsForSelectedDate: Object,
|
||||
premiumAppointmentFee: Object,
|
||||
estimatedServiceMinutesMinimum: Number,
|
||||
estimatedServiceMinutesMaximum: Number,
|
||||
validationRules: String,
|
||||
customComponentId: String,
|
||||
selectedDate: String,
|
||||
isSameDay: Boolean,
|
||||
displayWaitList: Boolean,
|
||||
selectedRouteCodeData: Object,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedRouteCode: null,
|
||||
timeSlotModalListButton: timeSlotModalListButton,
|
||||
selectedAnswerForDropOffOrInshop: null,
|
||||
selectedAnswerForTimeSlots: null,
|
||||
selectedAnswerForDropOffOrInshop: null,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.updateDropoffAndTimeSlotAnswersFromSelectedRouteCodeData(this.selectedRouteCodeData);
|
||||
this.autoSelectTimeSlotIfOnlyOneIsAvailable();
|
||||
},
|
||||
setup(props) {
|
||||
const uuid = uuidv4();
|
||||
const componentId = !props.customComponentId
|
||||
|
|
@ -186,20 +174,33 @@ export default {
|
|||
errors,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
waitListRequested(newVal) {
|
||||
if (newVal) {
|
||||
this.$nextTick(() => {
|
||||
this.scrollToSuccessMessage();
|
||||
});
|
||||
}
|
||||
},
|
||||
selectedRouteCodeData(newValue) {
|
||||
this.updateDropoffAndTimeSlotAnswersFromSelectedRouteCodeData(newValue);
|
||||
},
|
||||
timeSlotsForSelectedDate() {
|
||||
this.selectedAnswerForDropOffOrInshop = null;
|
||||
this.selectedAnswerForTimeSlots = null;
|
||||
this.autoSelectTimeSlotIfOnlyOneIsAvailable();
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
supplementalInformationBlock() {
|
||||
let appointmentTypeCmsWidgetName;
|
||||
|
||||
if (
|
||||
this.selectedDate == null ||
|
||||
this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF ||
|
||||
this.appointmentType === AppointmentTypeStrings.IN_SHOP ||
|
||||
this.appointmentType === AppointmentTypeStrings.DROP_OFF ||
|
||||
!this.availableTimeSlots
|
||||
) {
|
||||
if (!this.selectedAnswerForTimeSlots && !this.selectedAnswerForDropOffOrInshop) {
|
||||
this.autoSelectTimeSlotIfOnlyOneIsAvailable();
|
||||
}
|
||||
return null;
|
||||
// This is planned to be used again for drop-off
|
||||
// Wrote this to be ready for that eventuality, is untested and no HTML work done yet
|
||||
|
|
@ -214,11 +215,7 @@ export default {
|
|||
// );
|
||||
// }
|
||||
} else {
|
||||
if (!this.selectedAnswerForTimeSlots && this.selectedRouteCode) {
|
||||
// Clearing selectedRouteCode if no time slot is selected
|
||||
this.resetSelectedTimeSlot();
|
||||
}
|
||||
appointmentTypeCmsWidgetName = this.selectedRouteCode?.includes(
|
||||
appointmentTypeCmsWidgetName = this.selectedRouteCodeData?.routeCode?.includes(
|
||||
PREMIUM_TIME_SLOT_ID_FLAG
|
||||
)
|
||||
? this.mobilePremiumCmsWidgetName
|
||||
|
|
@ -299,13 +296,6 @@ export default {
|
|||
// return null;
|
||||
// }
|
||||
// },
|
||||
isSameDay() {
|
||||
if (!this.timeSlotsForSelectedDate) {
|
||||
return false;
|
||||
}
|
||||
const todaysDate = new Date().toISOString().split("T")[0];
|
||||
return this.selectedDate === todaysDate;
|
||||
},
|
||||
availableTimeSlots() {
|
||||
if (!this.timeSlotsForSelectedDate) {
|
||||
return null;
|
||||
|
|
@ -407,29 +397,60 @@ export default {
|
|||
},
|
||||
},
|
||||
methods: {
|
||||
initializeComponent() {
|
||||
this.setSelectedRouteCodeFromParent();
|
||||
},
|
||||
async setSelectedTimeSlot() {
|
||||
this.selectedRouteCode =
|
||||
this.selectedAnswerForTimeSlots || this.selectedAnswerForDropOffOrInshop;
|
||||
this.$emit(
|
||||
"update:modelValue",
|
||||
this.getSelectedTimeSlotInfoObject(this.selectedRouteCode)
|
||||
);
|
||||
},
|
||||
getRelevantDropOffCmsWidgetNameForSelectedTimeSlot(
|
||||
selectedRouteCode,
|
||||
isSameDayRelevant = false
|
||||
) {
|
||||
if (selectedRouteCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) {
|
||||
return this.overnightDropOffCmsWidgetName;
|
||||
} else if (selectedRouteCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) {
|
||||
return this.isSameDay && isSameDayRelevant
|
||||
? this.sameDayDropOffCmsWidgetName
|
||||
: this.dropoffCmsWidgetName;
|
||||
updateDropoffAndTimeSlotAnswersFromSelectedRouteCodeData(selectedRouteCodeData) {
|
||||
if (selectedRouteCodeData?.routeCode) {
|
||||
let routeCode = selectedRouteCodeData.routeCode;
|
||||
if (isDropOffRouteCode(routeCode)) {
|
||||
this.selectedAnswerForDropOffOrInshop = routeCode;
|
||||
} else {
|
||||
this.selectedAnswerForDropOffOrInshop = PICK_A_TIME_BUTTON_VALUE;
|
||||
if (this.selectedRouteCodeData.isPremiumAppointment) {
|
||||
routeCode = this.addPremiumFlagToInput(routeCode);
|
||||
}
|
||||
this.selectedAnswerForTimeSlots = routeCode;
|
||||
}
|
||||
} else {
|
||||
this.selectedAnswerForDropOffOrInshop = null;
|
||||
this.selectedAnswerForTimeSlots = null;
|
||||
}
|
||||
},
|
||||
dropOffSelectionChanged(newValue) {
|
||||
let newSelectedRouteCodeData = null;
|
||||
if (newValue && newValue != PICK_A_TIME_BUTTON_VALUE) {
|
||||
newSelectedRouteCodeData = {
|
||||
routeCode: newValue,
|
||||
isPremiumAppointment: false,
|
||||
};
|
||||
}
|
||||
this.selectedAnswerForTimeSlots = null;
|
||||
this.$emit("time-slot-selection-changed", newSelectedRouteCodeData);
|
||||
},
|
||||
timeSlotSelectionChanged(newValue) {
|
||||
if (newValue) {
|
||||
let routeCode = newValue;
|
||||
let isPremiumAppointment = routeCode.includes(PREMIUM_TIME_SLOT_ID_FLAG);
|
||||
if (isPremiumAppointment) {
|
||||
routeCode = this.removePremiumFlagFromInput(routeCode);
|
||||
}
|
||||
this.$emit("time-slot-selection-changed", {
|
||||
routeCode: routeCode,
|
||||
isPremiumAppointment: isPremiumAppointment,
|
||||
});
|
||||
}
|
||||
},
|
||||
// This is unused but planned to be used again
|
||||
// getRelevantDropOffCmsWidgetNameForSelectedTimeSlot(
|
||||
// selectedRouteCode,
|
||||
// isSameDayRelevant = false
|
||||
// ) {
|
||||
// if (selectedRouteCode.includes(RouteCodeFlags.OVERNIGHT_DROP_OFF)) {
|
||||
// return this.overnightDropOffCmsWidgetName;
|
||||
// } else if (selectedRouteCode.includes(RouteCodeFlags.ALL_DAY_DROP_OFF)) {
|
||||
// return this.isSameDay && isSameDayRelevant
|
||||
// ? this.sameDayDropOffCmsWidgetName
|
||||
// : this.dropoffCmsWidgetName;
|
||||
// }
|
||||
// },
|
||||
getAvailableTimeSlotsForInshop(timeSlotsForSelectedDate) {
|
||||
return timeSlotsForSelectedDate
|
||||
.filter((timeSlot) => {
|
||||
|
|
@ -463,8 +484,6 @@ export default {
|
|||
);
|
||||
}
|
||||
|
||||
this.resetSelectedTimeSlotIfDateChange(timeSlotsForSelectedDate);
|
||||
|
||||
return availableTimeSlots;
|
||||
},
|
||||
getPremiumAppointmentTimeSlot(timeSlotData) {
|
||||
|
|
@ -480,35 +499,19 @@ export default {
|
|||
},
|
||||
};
|
||||
},
|
||||
setSelectedRouteCodeFromParent() {
|
||||
if (!this.modelValue?.timeSlot?.routeCode) {
|
||||
return;
|
||||
}
|
||||
const routeCodeFromParent = this.modelValue.timeSlot.routeCode;
|
||||
if (this.modelValue?.isPremiumAppointment) {
|
||||
// Mobile Only
|
||||
this.selectedAnswerForTimeSlots = this.addPremiumFlagToInput(routeCodeFromParent);
|
||||
} else {
|
||||
if (isDropOffRouteCode(routeCodeFromParent)) {
|
||||
this.selectedAnswerForDropOffOrInshop = routeCodeFromParent;
|
||||
} else {
|
||||
this.selectedAnswerForDropOffOrInshop = PICK_A_TIME_BUTTON_VALUE;
|
||||
this.selectedAnswerForTimeSlots = routeCodeFromParent;
|
||||
}
|
||||
}
|
||||
},
|
||||
getWaitListRequestedFromStore() {
|
||||
return store.getters.order.customer?.waitListRequested;
|
||||
},
|
||||
autoSelectTimeSlotIfOnlyOneIsAvailable() {
|
||||
const numberOfOptions = this.timeSlotsForSelectedDate?.timeSlots?.length;
|
||||
if (this.appointmentType && numberOfOptions === 1) {
|
||||
if (numberOfOptions === 1) {
|
||||
if (this.availableTimeSlots.length > 0) {
|
||||
// this.availableTimeSlots only returns mobile/inshop slots so we know
|
||||
// the only available slot is not dropOFf
|
||||
this.selectedAnswerForTimeSlots = this.availableTimeSlots[0].value;
|
||||
} else {
|
||||
this.selectedAnswerForDropOffOrInshop = this.answersForDropOffQuestion[0].value;
|
||||
}
|
||||
this.setSelectedTimeSlot();
|
||||
}
|
||||
},
|
||||
addPremiumFlagToInput(routeCode) {
|
||||
|
|
@ -517,41 +520,6 @@ export default {
|
|||
removePremiumFlagFromInput(routeCode) {
|
||||
return routeCode.replace(PREMIUM_TIME_SLOT_ID_FLAG, "");
|
||||
},
|
||||
getSelectedTimeSlotInfoObject(routeCode) {
|
||||
const routeCodeIncludesPremium = routeCode?.includes(PREMIUM_TIME_SLOT_ID_FLAG);
|
||||
if (routeCodeIncludesPremium) {
|
||||
routeCode = this.removePremiumFlagFromInput(routeCode);
|
||||
}
|
||||
const timeSlot = this.timeSlotsForSelectedDate?.timeSlots?.find(
|
||||
(slot) => slot.id == routeCode
|
||||
);
|
||||
|
||||
if (timeSlot) {
|
||||
return {
|
||||
timeSlot: {
|
||||
date: this.timeSlotsForSelectedDate.date,
|
||||
routeCode: timeSlot.id,
|
||||
startTime: timeSlot.startTime,
|
||||
endTime: timeSlot.endTime,
|
||||
jobMaxMinutes: this.estimatedServiceMinutesMaximum?.toString() || null,
|
||||
jobMinMinutes: this.estimatedServiceMinutesMinimum?.toString() || null,
|
||||
},
|
||||
isPremiumAppointment: routeCodeIncludesPremium ? true : false,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
timeSlot: {
|
||||
date: null,
|
||||
routeCode: null,
|
||||
startTime: null,
|
||||
endTime: null,
|
||||
jobMaxMinutes: null,
|
||||
jobMinMinutes: null,
|
||||
},
|
||||
isPremiumAppointment: null,
|
||||
};
|
||||
},
|
||||
waitListChecked(event) {
|
||||
this.$emit("waitListRequested", event.target.checked);
|
||||
},
|
||||
|
|
@ -561,65 +529,6 @@ export default {
|
|||
successMessageElement.scrollIntoView({ behavior: "smooth" });
|
||||
}
|
||||
},
|
||||
resetSelectedTimeSlotIfDateChange(timeSlotsForSelectedDate) {
|
||||
if (this.selectedRouteCode) {
|
||||
const selectedRouteCodeString = this.selectedRouteCode.replace(
|
||||
PREMIUM_TIME_SLOT_ID_FLAG,
|
||||
""
|
||||
);
|
||||
const matchingTimeSlot = timeSlotsForSelectedDate.find((slot) => {
|
||||
return slot.id === selectedRouteCodeString;
|
||||
});
|
||||
if (!matchingTimeSlot) {
|
||||
this.resetSelectedTimeSlot();
|
||||
}
|
||||
}
|
||||
},
|
||||
resetSelectedTimeSlot() {
|
||||
this.selectedRouteCode = null;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
waitListRequested(newVal) {
|
||||
if (newVal) {
|
||||
this.$nextTick(() => {
|
||||
this.scrollToSuccessMessage();
|
||||
});
|
||||
}
|
||||
},
|
||||
modelValue: {
|
||||
handler(newValue) {
|
||||
this.handleChange(newValue);
|
||||
},
|
||||
deep: true,
|
||||
},
|
||||
selectedDate: {
|
||||
handler() {
|
||||
this.resetSelectedTimeSlot();
|
||||
this.selectedAnswerForDropOffOrInshop = null;
|
||||
this.selectedAnswerForTimeSlots = null;
|
||||
this.autoSelectTimeSlotIfOnlyOneIsAvailable();
|
||||
},
|
||||
},
|
||||
selectedRouteCode(newValue) {
|
||||
if (newValue) {
|
||||
this.setSelectedTimeSlot();
|
||||
}
|
||||
},
|
||||
selectedAnswerForDropOffOrInshop(newValue) {
|
||||
if (newValue == PICK_A_TIME_BUTTON_VALUE) {
|
||||
this.selectedRouteCode = null;
|
||||
this.setSelectedTimeSlot();
|
||||
} else {
|
||||
this.selectedAnswerForTimeSlots = null;
|
||||
this.selectedRouteCode = newValue;
|
||||
}
|
||||
},
|
||||
selectedAnswerForTimeSlots(newValue) {
|
||||
if (newValue) {
|
||||
this.selectedRouteCode = newValue;
|
||||
}
|
||||
},
|
||||
},
|
||||
components: {
|
||||
textBlock,
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ export async function getPricedMobileFeePart(serviceZipCode, pageNameToLog) {
|
|||
return null;
|
||||
}
|
||||
|
||||
const zipCodeData = await getZipCodeData(serviceZipCode);
|
||||
const providerData = await getShopProviderData(serviceZipCode);
|
||||
const zipCodeData = await getZipCodeData(serviceZipCode, pageNameToLog);
|
||||
const providerData = await getShopProviderData(serviceZipCode, pageNameToLog);
|
||||
|
||||
// Get the Mobile Fee Part
|
||||
const mobileFeePart = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
|
|
@ -50,7 +50,7 @@ export async function getPricedRecycleFeePart(serviceZipCode, pageNameToLog) {
|
|||
return null;
|
||||
}
|
||||
|
||||
const zipCodeData = await getZipCodeData(serviceZipCode);
|
||||
const zipCodeData = await getZipCodeData(serviceZipCode, pageNameToLog);
|
||||
|
||||
// Get supporting items
|
||||
const supportingItems = await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
|
|
@ -102,23 +102,23 @@ export async function getServiceabilityDetails(serviceZipCode, lineItems, pageNa
|
|||
);
|
||||
}
|
||||
|
||||
export async function getBillToAccountNumber(providerNumber) {
|
||||
export async function getBillToAccountNumber(providerNumber, pageNameToLog) {
|
||||
// Get the BillTo Account Number
|
||||
return await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
storeActions.GET_BILL_TO_ACCOUNT_NUMBER,
|
||||
{ providerNumber: providerNumber },
|
||||
"service-location",
|
||||
pageNameToLog,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
export async function getShopProviderData(serviceZipCode) {
|
||||
export async function getShopProviderData(serviceZipCode, pageNameToLog) {
|
||||
return await baseMixin.methods.dispatchStoreActionWithLogging(
|
||||
storeActions.GET_PROVIDERS,
|
||||
{
|
||||
serviceZipCode: serviceZipCode,
|
||||
},
|
||||
"service-location"
|
||||
pageNameToLog
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -139,6 +139,6 @@ export async function getClosestApplicableShops(serviceZipCode, carId, pageNameT
|
|||
return closestShops.data;
|
||||
}
|
||||
|
||||
export async function getZipCodeData(serviceZipCode) {
|
||||
return await baseMixin.methods.getZipCodeData(serviceZipCode, "service-location");
|
||||
export async function getZipCodeData(serviceZipCode, pageNameToLog) {
|
||||
return await baseMixin.methods.getZipCodeData(serviceZipCode, pageNameToLog);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -193,8 +193,7 @@ export default {
|
|||
return;
|
||||
}
|
||||
const zipCodeData = await this.getZipCodeData(
|
||||
this.internalModel.addressQuestions.zipCode,
|
||||
"service-location"
|
||||
this.internalModel.addressQuestions.zipCode
|
||||
);
|
||||
|
||||
if (!zipCodeData.isValid) {
|
||||
|
|
@ -216,26 +215,21 @@ export default {
|
|||
|
||||
// retrieve mobile fee part
|
||||
const serviceZipCode = this.internalModel.addressQuestions.zipCode;
|
||||
const mobileFeePart = await getPricedMobileFeePart(
|
||||
serviceZipCode,
|
||||
"service-location"
|
||||
);
|
||||
const mobileFeePart = await getPricedMobileFeePart(serviceZipCode, this.pageName);
|
||||
|
||||
// retrieve recycle fee part
|
||||
const recycleFeePart = await getPricedRecycleFeePart(
|
||||
serviceZipCode,
|
||||
"service-location"
|
||||
);
|
||||
const recycleFeePart = await getPricedRecycleFeePart(serviceZipCode, this.pageName);
|
||||
|
||||
// retrieve serviceability details
|
||||
const serviceabilityDetails = await getServiceabilityDetails(
|
||||
serviceZipCode,
|
||||
null,
|
||||
"service-location"
|
||||
this.pageName
|
||||
);
|
||||
|
||||
const billToAccountNumber = await getBillToAccountNumber(
|
||||
this.internalModel.zipCodeCtu
|
||||
this.internalModel.zipCodeCtu,
|
||||
this.pageName
|
||||
);
|
||||
|
||||
// update content related to service zip code
|
||||
|
|
|
|||
|
|
@ -226,17 +226,17 @@ export default {
|
|||
const cmsContentPromise = fetchCmsContentForPage(to.name);
|
||||
|
||||
const serviceZipCode = store.getters.order.serviceLocation.zipCode;
|
||||
const zipCodeDataPromise = getZipCodeData(serviceZipCode);
|
||||
const zipCodeDataPromise = getZipCodeData(serviceZipCode, to.name);
|
||||
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(
|
||||
serviceZipCode,
|
||||
null,
|
||||
"service-location"
|
||||
to.name
|
||||
);
|
||||
|
||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode, "service-location");
|
||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode, to.name);
|
||||
|
||||
const shopProviderDataPromise = getShopProviderData(serviceZipCode); // shopQuestion.methods.loadInitialData(serviceZipCode);
|
||||
const shopProviderDataPromise = getShopProviderData(serviceZipCode, to.name); // shopQuestion.methods.loadInitialData(serviceZipCode);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
|
|
@ -846,7 +846,7 @@ export default {
|
|||
zipCode: {
|
||||
handler(newValue) {
|
||||
if (!this.navigatingForward) {
|
||||
getShopProviderData(this.zipCode).then(async (result) => {
|
||||
getShopProviderData(this.zipCode, this.pageName).then(async (result) => {
|
||||
this.shopProviderData = result.data;
|
||||
if (this.selectedAppointmentType === "Mobile") {
|
||||
this.selectedProvider = new Provider(
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ export default {
|
|||
|
||||
const zipCodeData = await this.getZipCodeData(
|
||||
this.internalModel.zipCode,
|
||||
"service-location"
|
||||
this.pageName
|
||||
);
|
||||
|
||||
if (!zipCodeData.isValid) {
|
||||
|
|
@ -175,7 +175,7 @@ export default {
|
|||
const closestShops = await getClosestApplicableShops(
|
||||
this.internalModel.zipCode,
|
||||
this.carId,
|
||||
"service-location"
|
||||
this.pageName
|
||||
);
|
||||
|
||||
if (!closestShops || closestShops.inShopProviders?.length === 0) {
|
||||
|
|
@ -193,24 +193,25 @@ export default {
|
|||
const serviceZipCode = this.internalModel.zipCode;
|
||||
const mobileFeePart = await getPricedMobileFeePart(
|
||||
serviceZipCode,
|
||||
"service-location"
|
||||
this.pageName
|
||||
);
|
||||
|
||||
// retrieve recycle fee part
|
||||
const recycleFeePart = await getPricedRecycleFeePart(
|
||||
serviceZipCode,
|
||||
"service-location"
|
||||
this.pageName
|
||||
);
|
||||
|
||||
// retrieve serviceability details
|
||||
const serviceabilityDetails = await getServiceabilityDetails(
|
||||
serviceZipCode,
|
||||
null,
|
||||
"service-location"
|
||||
this.pageName
|
||||
);
|
||||
|
||||
const billToAccountNumber = await getBillToAccountNumber(
|
||||
this.internalModel.zipCodeCtu
|
||||
this.internalModel.zipCodeCtu,
|
||||
this.pageName
|
||||
);
|
||||
|
||||
// update content related to service zip code
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ export default {
|
|||
}
|
||||
this.isLoading = true;
|
||||
|
||||
this.zipCodeData = await this.getZipCodeData(this.localZipCode, "service-location");
|
||||
this.zipCodeData = await this.getZipCodeData(this.localZipCode, this.pageName);
|
||||
// Add zipCode to zipCodeData as it does not come back from endpoint
|
||||
this.zipCodeData.zipCode = this.localZipCode;
|
||||
if (this.zipCodeData.isValid) {
|
||||
|
|
@ -289,7 +289,7 @@ export default {
|
|||
const closestShops = await getClosestApplicableShops(
|
||||
this.localZipCode,
|
||||
this.$store.getters.order.vehicle.carId,
|
||||
"service-location"
|
||||
this.pageName
|
||||
);
|
||||
if (!closestShops || closestShops.inShopProviders?.length === 0) {
|
||||
this.isLoading = false;
|
||||
|
|
|
|||
|
|
@ -318,10 +318,6 @@ export default {
|
|||
"vin-lookup"
|
||||
);
|
||||
|
||||
// Update button "Continue with..."
|
||||
this.$refs.navbar.updateButtonText(
|
||||
`Continue with ${resultMap.vehicleLookupResponse.year} ${resultMap.vehicleLookupResponse.make} ${resultMap.vehicleLookupResponse.model}`
|
||||
);
|
||||
return this.$refs.navbar.removeLoader();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
import { applicationConfig } from "@/constants/application-config";
|
||||
|
||||
const externalUrls = {
|
||||
HERITAGE_FUNNEL: process.env.VUE_APP_HERITAGE_FUNNEL,
|
||||
SAFELITE_HOP: process.env.VUE_APP_SAFELITE_HOP,
|
||||
HERITAGE_FUNNEL: applicationConfig.HERITAGE_FUNNEL,
|
||||
SAFELITE_HOP: applicationConfig.SAFELITE_HOP,
|
||||
};
|
||||
|
||||
export { externalUrls };
|
||||
|
|
|
|||
|
|
@ -1,26 +1,21 @@
|
|||
<template>
|
||||
<loadingModal v-if="useLoadingModal" notFullScreen ref="loadingModal" />
|
||||
<a v-if="linkType === 'navigation'" @click="handleClick" class="navigation-link" :href="href">
|
||||
{{ text }}
|
||||
<slot name="after-text"></slot>
|
||||
</a>
|
||||
<!-- NOTE: each prettier-ignore is needed below...
|
||||
each anchor that follows needs to be one single line in markup or adds unwanted spaces within link (fixes CASH-1502) -->
|
||||
|
||||
<!-- prettier-ignore -->
|
||||
<a v-if="linkType === 'navigation'" @click="handleClick" class="navigation-link" :href="href">{{ text }}<slot name="after-text"></slot></a>
|
||||
<!-- prettier-ignore -->
|
||||
<a
|
||||
v-else-if="linkType === 'newWindowLink'"
|
||||
@click="handleClick"
|
||||
class="new-window-link"
|
||||
:href="href"
|
||||
target="_blank">
|
||||
{{ text }}
|
||||
<slot name="after-text"></slot>
|
||||
</a>
|
||||
<a v-else-if="linkType === 'textSmall'" @click="handleClick" class="small" :href="href">
|
||||
{{ text }}
|
||||
<slot name="after-text"></slot>
|
||||
</a>
|
||||
<a v-else-if="linkType === 'text'" @click="handleClick" :href="href">
|
||||
{{ text }}
|
||||
<slot name="after-text"></slot>
|
||||
</a>
|
||||
target="_blank">{{ text }}<slot name="after-text"></slot></a>
|
||||
<!-- prettier-ignore -->
|
||||
<a v-else-if="linkType === 'textSmall'" @click="handleClick" class="small" :href="href">{{ text }}<slot name="after-text"></slot></a>
|
||||
<!-- prettier-ignore -->
|
||||
<a v-else-if="linkType === 'text'" @click="handleClick" :href="href">{{ text }}<slot name="after-text"></slot></a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
|
|||
|
|
@ -1,20 +1,5 @@
|
|||
process.env.VUE_APP_CONSUMER_CF_DISTRO = "https://digitalapi.dev.safelite.io";
|
||||
//process.env.VUE_APP_HERITAGE_FUNNEL = "http://localhost:38000/default.aspx";
|
||||
process.env.VUE_APP_HERITAGE_FUNNEL = "https://fixmyglassdev.safelite.com/default.aspx";
|
||||
process.env.VUE_APP_GOOGLE_PLACES_API_KEY = "AIzaSyDptGCkOPgN2uWJOy4ou4M33phRD4MAoJo";
|
||||
process.env.VUE_APP_CURRENT_ENVIRONMENT = "Localhost";
|
||||
process.env.VUE_APP_MY_ACCOUNT = "https://myaccountdev.safelite.com/";
|
||||
//process.env.VUE_APP_SAFELITE_HOP = "http://localhost:60966/fmgCheckoutShared.aspx";
|
||||
process.env.VUE_APP_SAFELITE_HOP = "https://sv2-safelitehop-dev.safelite.com/fmgCheckoutShared.aspx";
|
||||
process.env.VUE_APP_SOLARWINDS_MONITORING = "";
|
||||
process.env.VUE_APP_SESSION_TIMEOUT_MINUTES = 30;
|
||||
|
||||
// GA & GTM
|
||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
|
||||
"(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl+ '>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x';f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-M6XCRH');";
|
||||
|
||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC =
|
||||
"https://www.googletagmanager.com/ns.html?id=GTM-M6XCRH>m_auth=amlAYNhxUxuskQo7jmjadg>m_preview=env-38>m_cookies_win=x";
|
||||
const webpack = require('webpack');
|
||||
const { environmentVariablesWithDefaults } = require('./environment-variables.js');
|
||||
|
||||
module.exports = {
|
||||
outputDir: "dist/fmg",
|
||||
|
|
@ -36,5 +21,8 @@ module.exports = {
|
|||
},
|
||||
configureWebpack: {
|
||||
devtool: "source-map",
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(environmentVariablesWithDefaults),
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,16 +1,5 @@
|
|||
process.env.VUE_APP_CONSUMER_CF_DISTRO = "__VUE_APP_CONSUMER_CF_DISTRO__";
|
||||
process.env.VUE_APP_GOOGLE_PLACES_API_KEY = "__VUE_APP_GOOGLE_PLACES_API_KEY__";
|
||||
process.env.VUE_APP_HERITAGE_FUNNEL = "__VUE_APP_HERITAGE_FUNNEL__";
|
||||
process.env.VUE_APP_CURRENT_ENVIRONMENT = "__VUE_APP_CURRENT_ENVIRONMENT__";
|
||||
process.env.VUE_APP_MY_ACCOUNT = "__VUE_APP_MY_ACCOUNT__";
|
||||
process.env.VUE_APP_SAFELITE_HOP = "__VUE_APP_SAFELITE_HOP__";
|
||||
process.env.VUE_APP_SOLARWINDS_MONITORING_SCRIPT = "__VUE_APP_SOLARWINDS_MONITORING_SCRIPT__";
|
||||
process.env.VUE_APP_SESSION_TIMEOUT_MINUTES = 30;
|
||||
|
||||
// GA & GTM
|
||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY = "__VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY__";
|
||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC =
|
||||
"__VUE_APP_GOOGLE_TAG_MANAGER_NOSCRIPT_FRAME_SRC__";
|
||||
const webpack = require('webpack');
|
||||
const { environmentVariablesWithoutDefaults } = require('./environment-variables.js');
|
||||
|
||||
module.exports = {
|
||||
outputDir: "dist/fmg",
|
||||
|
|
@ -30,4 +19,9 @@ module.exports = {
|
|||
},
|
||||
},
|
||||
},
|
||||
configureWebpack: {
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin(environmentVariablesWithoutDefaults),
|
||||
],
|
||||
},
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue