Merge pull request #178 from Safelite/feature/digital/SSR-219

Feature/digital/ssr 219
This commit is contained in:
katiekroell 2023-03-01 10:31:03 -05:00 committed by GitHub
commit 41d827e9c8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 270 additions and 20 deletions

View file

@ -1,7 +1,8 @@
const dynamicStrings = {
GLOBAL_STATE: "globalState",
CUSTOM: "custom",
ROUTER_LINK: "routerLink:"
ROUTER_LINK: "routerLink:",
TEXT_LINK: "textLink:"
};
export { dynamicStrings };

View file

@ -181,10 +181,14 @@ function mapStringToState(str) {
return stringBuilder.trimStart();
}
export function doesCopyContainRouterLink(copy) {
export function doesCopyContainRouterLink(copy) {
return copy.includes(this.dynamicStrings.ROUTER_LINK);
}
export function doesCopyContainTextLink(copy) {
return copy.includes(this.dynamicStrings.TEXT_LINK);
}
export function splitCopyOnCMSPlaceHolder(copy) {
// splits copy on { ... } such as {routerlink: ...}
return copy.split(/{(.*?)}/g);

View file

@ -8,11 +8,6 @@
<siteHeader
cmsWidgetName="SiteHeaderWidget"
/>
<vehicleBanner
cmsWidgetName="VehicleBannerWidget"
:displayGenericVehicleImage="false"
class="mb-0"
/>
<div class="fade-on-route-transition sub-container make-tall px-5">
<textBlock
cmsWidgetName="verifyingCoverageStatement"
@ -20,21 +15,49 @@
justifyText="center"
class="mt-4 mb-4"
/>
<textBlock
cmsWidgetName="continueWithSchedulingCopy"
typeStyle="body"
class="mt-0"
<div
v-html="continueWithSchedulingBodyText"
class="mt-0"
/>
<textBlock
cmsWidgetName="whatHappensNextCopy"
class="mt-4 mb-2 fw-bold"
/>
<textBlock
cmsWidgetName="UnverifiedADASNextStepsWidget"
typeStyle="body"
/>
<a href="#!" data-bs-toggle="modal" data-bs-target="#RecalModal" aria-label="Modal window">Recalibration</a>
<modal cmsWidgetName="RecalModal" />
<div v-if="unverifiedADASNextSteps">
<ol>
<li v-for="listItem in this.arrayOfListItemsFromBodyText" :key="listItem">
<!-- no textLink -->
<span
v-if="!doesCopyContainTextLink(listItem)"
v-html="listItem"></span>
<!-- with textLink-->
<template
v-else
v-for="copy in splitCopyOnCMSPlaceHolder(listItem)"
:key="copy">
<span v-if="!doesCopyContainTextLink(copy)" v-html="copy"></span>
<span v-else>
<textLink
linkType="text"
:text="getRouterLinkDisplayTextFromCopy(copy)"
href="#!"
data-bs-toggle="modal"
data-bs-target="#RecalModal"
aria-label="Modal window" />
</span>
</template>
</li>
</ol>
</div>
<div
v-if="unverifiedNonADASNextSteps"
v-html="unverifiedNonADASNextStepsBodyText" >
</div>
<div
v-if="unverifiedNonADASRepair"
v-html="unverifiedNonADASRepairBodyText" >
</div>
<recalModal cmsWidgetName="RecalModal" />
<siteFooter
cmsWidgetName="SiteFooterWidget"
:isForwardActionDisabled="!meta.valid"
@ -57,10 +80,20 @@ import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue'
import vehicleBanner from '@/iss-components/vehicle-banner/vehicle-banner.vue';
import textBlock from "@/digital-components/text-block/text-block";
import modal from "@/digital-components/modal/modal";
import textLink from '@/ux-components/text-link/text-link.vue';
import recalModal from '@/layouts/coverage-statement/recal-modal/recal-modal.vue';
// Import Supporting Files
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
import {
fetchCmsContentForPage,
doesCopyContainTextLink,
splitCopyOnCMSPlaceHolder,
getRouterLinkDisplayTextFromCopy,
getRouterLinkRouteFromCopy
} from '@/helpers/cms-content-helper';
import { settleAllPromises } from '@/helpers/layout-helper';
import { getDamageString } from '@/helpers/damage-helper.js';
import { useMainStore } from "@/store";
export default {
name: 'coverage-statement',
@ -73,11 +106,49 @@ export default {
vehicleBanner,
textBlock,
modal,
textLink,
recalModal
},
data() {
return {};
return {
isRepair: useMainStore().order.damage.isRepair,
unverifiedADASNextSteps: false,
unverifiedNonADASNextSteps: false,
unverifiedNonADASRepair: false,
};
},
created() {
// check if repair or replace, if repair, display NonADASRepair
if (this.isRepair) {
this.unverifiedNonADASRepair = true;
}
else {
this.displayReplaceCoverageStatement();
}
},
computed: {
continueWithSchedulingBodyText() {
return this.getCmsContent('continueWithSchedulingCopy', 'BodyText');
},
unverifiedADASNextStepsBodyText() {
return this.getCmsContent('UnverifiedADASNextStepsWidget', 'BodyText').replaceAll("{custom:damage}", getDamageString());
},
unverifiedNonADASNextStepsBodyText() {
return this.getCmsContent('UnverifiedNonADASNextStepsWidget', 'BodyText').replaceAll("{custom:damage}", getDamageString());
},
unverifiedNonADASRepairBodyText() {
return this.getCmsContent('UnverifiedNonADASRepairWidget', 'BodyText');
},
splitADASCoverageStatementCopy() {
// Splits content when brackets are found in text so that text can be looped through and text-link can be injected when needed
return this.splitCopyOnCMSPlaceHolder(this.unverifiedADASNextStepsBodyText);
},
arrayOfListItemsFromBodyText() {
return this.getArrayOfListItemsFromRawCmsCopy(this.unverifiedADASNextStepsBodyText);
}
},
async beforeRouteEnter(to, from, next) {
// Call APIs
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
// Settle promises and get results
@ -95,6 +166,10 @@ export default {
});
},
methods: {
doesCopyContainTextLink,
splitCopyOnCMSPlaceHolder,
getRouterLinkDisplayTextFromCopy,
getRouterLinkRouteFromCopy,
arePagePrerequisiteValid() {
return true;
},
@ -104,9 +179,35 @@ export default {
*/
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
},
displayReplaceCoverageStatement() {
// get array of parts for vehicle
let parts = useMainStore().order.lineItems.glassParts;
// loop through parts to check for ADAS
for (let part of parts) {
// if ADAS, display ADASNextSteps
if (part.requiresRecalibration) {
this.unverifiedADASNextSteps = true
}
// if non-ADAS, display NonADASNextSteps
else {
this.unverifiedNonADASNextSteps = true
}
}
},
stripOlTagFromCopy(copy) {
const regex = /(?:<ol(?:.*?)>)|(?:<\/ol>)/g;
return copy.replace(regex, "");
},
getArrayOfListItemsFromRawCmsCopy(copy) {
const withoutOlTags = this.stripOlTagFromCopy(copy);
return withoutOlTags
.split(/(?:<li(?:.*?)>)|(?:<\/li>)/g)
.filter((lineItem) => lineItem);
},
},
async forwardButtonAction() {},
resetDependentState() {},
},
};
</script>

View file

@ -0,0 +1,144 @@
<template>
<!-- Modal -->
<div
class="modal fade modal-component"
v-on="{ 'hidden.bs.modal': resetButtonStyle }"
:id="cmsWidgetName"
tabindex="-1"
aria-labelledby="ModalComponentLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"></button>
</div>
<div class="modal-body ps-4 pe-4 pt-4 pb-4">
<h5 class="mb-4 text-center" v-html="ModalHeadline"></h5>
<img :src="ModalImage" class="mw-100 d-flex mx-auto mb-4" alt="" />
<p class="fw-bold mb-2 subheader-text" v-html="ModalSubheadertext"></p>
<p class="mb-0" v-html="ModalBodyText"></p>
<p
class="my-4 caption modal-sub-body"
v-if="ModalSubBodyText"
v-html="ModalSubBodyText"></p>
</div>
<div class="modal-footer px-5 py-4">
<buttonMain
isPrimary
class="w-100"
ref="buttonMain"
suppressLoader
:buttonText="ModalCloseButtonText"
@click-event="buttonClick"
data-bs-dismiss="modal" />
</div>
</div>
</div>
</div>
</template>
<script>
import buttonMain from "@/ux-components/button-main/button-main";
export default {
name: "modal",
props: {
cmsWidgetName: String,
},
computed: {
ModalHeadline() {
return this.getCmsContent(this.cmsWidgetName, "HeaderText");
},
ModalSubheadertext() {
return this.getCmsContent(this.cmsWidgetName, "SubheaderText");
},
ModalBodyText() {
return this.getCmsContent(this.cmsWidgetName, "BodyText");
},
ModalSubBodyText() {
return this.getCmsContent(this.cmsWidgetName, "BodyText2");
},
ModalImage() {
return this.getCmsContent(this.cmsWidgetName, "Image");
},
ModalCloseButtonText() {
return this.getCmsContent(this.cmsWidgetName, "FooterText");
},
},
methods: {
resetButtonStyle() {
this.$refs.buttonMain.resetButtonStyle();
},
},
components: {
buttonMain,
},
};
</script>
<style lang="scss">
.modal {
top: auto;
bottom: 0;
h5,
strong,
.subheader-text {
color: $black;
}
.modal-header {
border-bottom: none;
.btn-close {
background-image: url("data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M15.6874 1.82179L9.50889 8L15.6874 14.1782C16.1042 14.595 16.1042 15.2707 15.6874 15.6875C15.4843 15.8907 15.2146 16 14.9328 16C14.6514 16 14.3818 15.8906 14.1787 15.6875L8.00017 9.50934L1.82171 15.6875C1.6182 15.8907 1.34876 16 1.06708 16C0.785733 16 0.516056 15.8906 0.312965 15.6875C-0.10429 15.2706 -0.10429 14.5952 0.312797 14.1784L6.03276 8.45867L6.49146 8L0.312945 1.82177C-0.10429 1.40483 -0.10429 0.729418 0.312797 0.31262C0.728936 -0.104145 1.40489 -0.104051 1.82185 0.31262L7.54152 6.03202L8.00017 6.49065L14.1786 0.312472C14.5955 -0.104107 15.2707 -0.104201 15.6874 0.312452C16.1042 0.729289 16.1042 1.40496 15.6874 1.82179Z' fill='%231574A1'/%3E%3C/svg%3E%0A");
opacity: 1;
}
}
&.modal-component {
.modal-dialog {
max-width: 576px;
margin: 0 auto;
.modal-content {
margin: 0 auto;
box-shadow: 0px 16px 48px -16px rgba(0, 0, 0, 0.25);
border-radius: 1.5rem 1.5rem 0 0;
.modal-body {
.modal-sub-body {
color: $gray-600;
}
ul {
margin-bottom: 0;
}
p {
&:last-child {
margin-bottom: 0;
}
}
}
}
&.modal-dialog-centered {
align-items: flex-end;
min-height: 100%;
}
}
.modal-footer {
border-top: none;
background-color: $gray-100;
box-shadow: 0px -1px 0px rgba(179, 180, 181, 0.3);
button {
margin: 0;
}
}
}
}
body {
.modal-backdrop {
height: 100%;
&.show {
opacity: 0.4;
}
}
}
</style>