CASH-109 return user page
CASH-109 return user page for when a session times out
This commit is contained in:
parent
66da230cc9
commit
9822cdfedf
11 changed files with 144 additions and 10 deletions
|
|
@ -37,6 +37,8 @@ const applicationConfig = {
|
||||||
FRONTEND_LOGGER_PATH: "/analytics/api/v1/logging",
|
FRONTEND_LOGGER_PATH: "/analytics/api/v1/logging",
|
||||||
AFFILIATE_COOKIE_CONTAINING_NAME: "_Track",
|
AFFILIATE_COOKIE_CONTAINING_NAME: "_Track",
|
||||||
COOKIE_NAME_LENGTH_MAX_LIMIT: 44,
|
COOKIE_NAME_LENGTH_MAX_LIMIT: 44,
|
||||||
|
SESSION_TIMEOUT_MINUTES: process.env.VUE_APP_SESSION_TIMEOUT_MINUTES,
|
||||||
|
RETURN_USER_PAGE: "/fmg/?fmgPage=return-user",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { applicationConfig };
|
export { applicationConfig };
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ const cookieNames = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const cookieExpirations = {
|
const cookieExpirations = {
|
||||||
SESSION_ID: convertToSeconds({ minutes: 30 }),
|
SESSION_ID: convertToSeconds({ minutes: applicationConfig.SESSION_TIMEOUT_MINUTES }),
|
||||||
DXDEV: convertToSeconds({ years: 1 }),
|
DXDEV: convertToSeconds({ years: 1 }),
|
||||||
FUNNEL_USER_ID: convertToSeconds({ weeks: 1 }),
|
FUNNEL_USER_ID: convertToSeconds({ weeks: 1 }),
|
||||||
FUNNEL_SESSION_KEY: convertToSeconds({ minutes: 30 }),
|
FUNNEL_SESSION_KEY: convertToSeconds({ minutes: 30 }),
|
||||||
|
|
|
||||||
|
|
@ -217,11 +217,11 @@ export default {
|
||||||
flex: none;
|
flex: none;
|
||||||
}
|
}
|
||||||
.textbox-question {
|
.textbox-question {
|
||||||
padding: .25rem 0;
|
padding: 0.25rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.modal-dialog-centered {
|
&.modal-dialog-centered {
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,10 @@ export default {
|
||||||
|
|
||||||
// hide save progress button; show success message alert
|
// hide save progress button; show success message alert
|
||||||
this.isProgressSaved = true;
|
this.isProgressSaved = true;
|
||||||
|
|
||||||
// communicate to parent the new status
|
// communicate to parent the new status
|
||||||
this.$emit("save-progress-saved");
|
this.$emit("save-progress-saved");
|
||||||
|
|
||||||
this.modal.closeModal();
|
this.modal.closeModal();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,7 @@ export default {
|
||||||
currentPage: pageNameToLog,
|
currentPage: pageNameToLog,
|
||||||
endpoint: endpoint,
|
endpoint: endpoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
router.navigateError(errorPayload);
|
router.navigateError(errorPayload);
|
||||||
|
|
||||||
// do not log 404 errors from services because we return NotFound
|
// do not log 404 errors from services because we return NotFound
|
||||||
|
|
|
||||||
|
|
@ -621,7 +621,7 @@ export default {
|
||||||
: this.$store.getters.order.serviceLocation?.appointmentType;
|
: this.$store.getters.order.serviceLocation?.appointmentType;
|
||||||
},
|
},
|
||||||
ServiceLocationFullAddressText() {
|
ServiceLocationFullAddressText() {
|
||||||
return `${this.ServiceLocationAddress.toLowerCase()}${this.ServiceLocationAddress2 ? ", " + this.ServiceLocationAddress2 : ""}, ${this.ServiceLocationCity.toLowerCase()}, ${this.ServiceLocationState} ${this.ServiceLocationZipCode}`;
|
return `${this.ServiceLocationAddress?.toLowerCase()}${this.ServiceLocationAddress2 ? ", " + this.ServiceLocationAddress2 : ""}, ${this.ServiceLocationCity?.toLowerCase()}, ${this.ServiceLocationState} ${this.ServiceLocationZipCode}`;
|
||||||
},
|
},
|
||||||
ServiceLocationFullAddress() {
|
ServiceLocationFullAddress() {
|
||||||
if (this.AppointmentType === AppointmentTypeStrings.MOBILE) {
|
if (this.AppointmentType === AppointmentTypeStrings.MOBILE) {
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
displayContent() {
|
displayContent() {
|
||||||
return [
|
return [
|
||||||
`${this.addressInfo.address.toLowerCase()}${this.addressInfo.address2 ? ", " : ""}${this.addressInfo.address2.toLowerCase()}, ${this.addressInfo.city.toLowerCase()}, ${this.addressInfo.state} ${this.addressInfo.zipCode}`,
|
`${this.addressInfo?.address?.toLowerCase()}${this.addressInfo?.address2 ? ", " : ""}${this.addressInfo?.address2?.toLowerCase()}, ${this.addressInfo?.city?.toLowerCase()}, ${this.addressInfo.state} ${this.addressInfo.zipCode}`,
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
addressInfo() {
|
addressInfo() {
|
||||||
|
|
|
||||||
118
src/layouts/return-user/return-user.vue
Normal file
118
src/layouts/return-user/return-user.vue
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
<template>
|
||||||
|
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
||||||
|
<div class="return-user small-question-text">
|
||||||
|
<loadingModal ref="loadingModal" />
|
||||||
|
<div class="container-fluid page-container-grouped-styles">
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6 col-xl-4 mt-4">
|
||||||
|
<funnelSubHeader
|
||||||
|
ref="funnelSubHeader"
|
||||||
|
cmsWidgetName="FunnelSubHeaderWidget" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6 col-xl-4">
|
||||||
|
<navbar
|
||||||
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
ref="navbar"
|
||||||
|
buttonSize
|
||||||
|
:isBackButtonHidden="true"
|
||||||
|
@ForwardClicked="forwardButtonAction" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-6 col-xl-4 start-over">
|
||||||
|
<a @click="startOver" alt="Start Over Button"
|
||||||
|
><img v-bind:src="startOverImage" />{{ startOverText }}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Components
|
||||||
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||||
|
// Supporting Files
|
||||||
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import { Form } from "vee-validate";
|
||||||
|
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
import { deleteFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "return-user",
|
||||||
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
// Call APIs
|
||||||
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
// Settle promises and get results
|
||||||
|
const promiseResultMap = [
|
||||||
|
{
|
||||||
|
resultKey: "cmsContent",
|
||||||
|
promise: cmsContentPromise,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
// Call the "next" function to complete the transition to this page.
|
||||||
|
next((vm) => {
|
||||||
|
vm.setCmsContent(resultMap.cmsContent);
|
||||||
|
vm.startOverText = resultMap.cmsContent.StartOverWidget.HeaderText;
|
||||||
|
vm.startOverImage = resultMap.cmsContent.StartOverWidget.Image;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
startOverText: "",
|
||||||
|
startOverImage: null,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
arePagePrerequisitesValid() {
|
||||||
|
return getFunnelCookie() !== null;
|
||||||
|
},
|
||||||
|
|
||||||
|
async forwardButtonAction() {
|
||||||
|
// clicking continue and use no page name to trigger the implicit navigation in router
|
||||||
|
window.location.href = "/fmg/";
|
||||||
|
},
|
||||||
|
|
||||||
|
async startOver() {
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.$route.query[this.queryStrings.FMG_PAGE],
|
||||||
|
this.GaActions.CLICKED,
|
||||||
|
"Start over",
|
||||||
|
true
|
||||||
|
);
|
||||||
|
deleteFunnelCookie();
|
||||||
|
await this.dispatchStoreAction(storeActions.RESET_STATE);
|
||||||
|
window.location.href = "/fmg/";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
Form,
|
||||||
|
funnelHeader,
|
||||||
|
funnelSubHeader,
|
||||||
|
navbar,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.start-over {
|
||||||
|
text-align: center;
|
||||||
|
a {
|
||||||
|
font-weight: 600;
|
||||||
|
color: $black;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -26,6 +26,7 @@ import store from "@/store";
|
||||||
|
|
||||||
import baseMixin from "@/mixins/base-mixin";
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
import { applicationConfig } from "../constants/application-config";
|
import { applicationConfig } from "../constants/application-config";
|
||||||
|
import { getFunnelCookie } from "@/helpers/heritage-integration/cookie-helper";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -651,7 +652,6 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
pushPageErrorToDataLayer(error) {
|
pushPageErrorToDataLayer(error) {
|
||||||
|
|
||||||
pushToDataLayerIfDefined({
|
pushToDataLayerIfDefined({
|
||||||
event: "page-error",
|
event: "page-error",
|
||||||
error: error,
|
error: error,
|
||||||
|
|
@ -710,6 +710,17 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
async validateSession() {
|
async validateSession() {
|
||||||
|
// The noSession function checks the cookies related to analytics logging(sid). it is not the funnel info cookie.
|
||||||
|
// The sid cookie for analytics will expire every 30 minutes and get recreated in initSession. If this happens
|
||||||
|
// and we also have the funnel cookie present, that indicates they have an existing session that is now expired
|
||||||
|
// so route them to the return user page.
|
||||||
|
const funnelCookieLastTouched = getFunnelCookie()?.LastTouched;
|
||||||
|
if (this.noSession() && funnelCookieLastTouched !== null && funnelCookieLastTouched !== undefined) {
|
||||||
|
await this.initSession();
|
||||||
|
window.location.href = applicationConfig.RETURN_USER_PAGE;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (this.noSession()) {
|
if (this.noSession()) {
|
||||||
await this.initSession();
|
await this.initSession();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,10 @@ const fmgPageValues = {
|
||||||
PAYMENT: "payment",
|
PAYMENT: "payment",
|
||||||
PAYMENT_PIA_RETURN: "payment-pia-return",
|
PAYMENT_PIA_RETURN: "payment-pia-return",
|
||||||
CONFIRMATION: "confirmation",
|
CONFIRMATION: "confirmation",
|
||||||
|
RETURN_USER: "return-user",
|
||||||
};
|
};
|
||||||
|
|
||||||
const funnelStartPageName = fmgPageValues.VEHICLE;
|
const funnelStartPageName = fmgPageValues.VEHICLE;
|
||||||
|
const returnUserPageName = fmgPageValues.RETURN_USER;
|
||||||
|
|
||||||
export { fmgPageValues, funnelStartPageName };
|
export { fmgPageValues, funnelStartPageName, returnUserPageName };
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ 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 = "http://localhost:60966/fmgCheckoutShared.aspx";
|
||||||
process.env.VUE_APP_SAFELITE_HOP = "https://sv2-safelitehop-dev.safelite.com/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_SOLARWINDS_MONITORING = "";
|
||||||
|
process.env.VUE_APP_SESSION_TIMEOUT_MINUTES = 30;
|
||||||
|
|
||||||
// GA & GTM
|
// GA & GTM
|
||||||
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
|
process.env.VUE_APP_GOOGLE_TAG_MANAGER_SCRIPT_BODY =
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue