Merge branch 'release/2025.08.21' into rlsmerge/2025.08.21-to-dev
This commit is contained in:
commit
c65f214feb
40 changed files with 597 additions and 334 deletions
|
|
@ -27,4 +27,3 @@ ADMIN_SERVICE_API_URL="https://issadminapi.dev.sagaws.net/iss-admin/api/v1/"
|
|||
|
||||
# API authentication (replace with actual value when running tests)
|
||||
CCIS_API_AUTH="undefined"
|
||||
|
||||
|
|
|
|||
|
|
@ -131,24 +131,24 @@ export class BasePage {
|
|||
}
|
||||
|
||||
async validateProgressBar(progressPercentage: string, timeout: number = 60000) {
|
||||
// This section has been commented out until progress bar work is completed for parity.
|
||||
|
||||
|
||||
await waitUntil(async () => {
|
||||
let loaderElements = await this.page.locator('button .loader, .buy-loader, timeout, .modal-loader').all();
|
||||
return !(await Promise.any(loaderElements.map(el => el.isVisible())).catch(() => false));
|
||||
});
|
||||
// await waitUntil(async () => {
|
||||
// let loaderElements = await this.page.locator('button .loader, .buy-loader, timeout, .modal-loader').all();
|
||||
// return !(await Promise.any(loaderElements.map(el => el.isVisible())).catch(() => false));
|
||||
// });
|
||||
|
||||
// Take a screenshot of the page before validating the progress bar
|
||||
await this.page.screenshot({ path: `test-results\\ortoni-data\\progress-bar-${Date.now()}.png`, fullPage: true });
|
||||
// Wait until the progress bar element is attached and visible
|
||||
// // Take a screenshot of the page before validating the progress bar
|
||||
// await this.page.screenshot({ path: `test-results\\ortoni-data\\progress-bar-${Date.now()}.png`, fullPage: true });
|
||||
// // Wait until the progress bar element is attached and visible
|
||||
|
||||
const actualProgressPercentage = await this.progressBar.evaluate(
|
||||
async (element) => {
|
||||
await new Promise(resolve => setTimeout(resolve, 200));
|
||||
return element.style.width || "Not Found";
|
||||
}
|
||||
);
|
||||
Soft.expect(actualProgressPercentage).toBe(progressPercentage);
|
||||
console.log(`Progress Bar Percentage: Actual - ${actualProgressPercentage} vs Expected - ${progressPercentage}`);
|
||||
// const actualProgressPercentage = await this.progressBar.evaluate(
|
||||
// async (element) => {
|
||||
// await new Promise(resolve => setTimeout(resolve, 200));
|
||||
// return element.style.width || "Not Found";
|
||||
// }
|
||||
// );
|
||||
// Soft.expect(actualProgressPercentage).toBe(progressPercentage);
|
||||
// console.log(`Progress Bar Percentage: Actual - ${actualProgressPercentage} vs Expected - ${progressPercentage}`);
|
||||
}
|
||||
}
|
||||
|
|
@ -17,7 +17,7 @@ export class SchedulePage extends BasePage {
|
|||
readonly militaryWarningMessage: Locator;
|
||||
readonly changeZipButton: Locator;
|
||||
readonly updateZipTextBox: Locator;
|
||||
readonly saveZipButton: Locator;
|
||||
readonly saveLocationButton: Locator;
|
||||
readonly changeShopLocationLink: Locator;
|
||||
readonly selectAShopOptions: Locator;
|
||||
readonly yourSafeliteShop: Locator;
|
||||
|
|
@ -37,14 +37,14 @@ export class SchedulePage extends BasePage {
|
|||
super(page);
|
||||
this.page = page;
|
||||
|
||||
this.inShopButton = this.page.getByText(/In-shop/);
|
||||
this.mobileButton = this.page.locator('label[buttonlabel="Mobile"]');
|
||||
this.inShopButton = this.page.locator('label[buttonlabel="You come to our store"]');
|
||||
this.mobileButton = this.page.locator('label[buttonlabel="Our mobile shop comes to you"]');
|
||||
this.RecalWarningMessage1 = this.page.getByText(/We're not able to provide mobile service/);
|
||||
this.RecalWarningMessage2 = this.page.getByText(/advanced safety system recalibration needs to be done in our shop./);
|
||||
this.militaryWarningMessage = this.page.locator('[class*="widget-name-AlertMilitaryBaseZipWidget"]');
|
||||
this.changeZipButton = this.page.locator('a:has(span.sr-only:has-text("edit zip code"))');
|
||||
this.updateZipTextBox = this.page.locator('#serviceZipCode').filter({ visible: true });
|
||||
this.saveZipButton = this.page.getByText('Save ZIP code', { exact: true });
|
||||
this.saveLocationButton = this.page.getByText('Save location', { exact: true });
|
||||
this.changeShopLocationLink = this.page.locator(".shop-question a").filter({ hasText: "Change shop location " });
|
||||
this.selectAShopOptions = this.page.locator('[class="shop-question"]');
|
||||
this.yourSafeliteShop = this.page.locator("fieldset:has(#chooseShop) label");
|
||||
|
|
@ -82,10 +82,11 @@ export class SchedulePage extends BasePage {
|
|||
if (zipCodeMatch) {
|
||||
const zipCode = zipCodeMatch[0];
|
||||
// Enter the ZIP code into the updateZipTextBox
|
||||
await this.changeZipButton.click();
|
||||
await this.changeShopLocationLink.click();
|
||||
await this.page.waitForTimeout(500);
|
||||
await this.updateZipTextBox.fill(zipCode);
|
||||
await this.saveZipButton.click();
|
||||
// Click the save location button
|
||||
await this.saveLocationButton.click();
|
||||
}
|
||||
|
||||
await this.inShopButton.click();
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ const cashReplaceGlassPromoInshopTests: ITestCase[] = [];
|
|||
|
||||
const tc = {
|
||||
name: `CashReplaceGlassPromoInshop`,
|
||||
tags: ['@E2E','@CashReplaceGlassPromoInshop', '@test_report', '@CASH'],
|
||||
tags: ['@E2E','@CashReplaceGlassPromoInshop', '@test_report', '@CASH', '@CASH-1182'],
|
||||
testData: cashReplaceGlassPromoInshopData
|
||||
};
|
||||
cashReplaceGlassPromoInshopTests.push(tc);
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ const cashReplaceMultiGlassMobileTests: ITestCase[] = [];
|
|||
|
||||
const tc = {
|
||||
name: `CashReplaceMultiGlassMobile`,
|
||||
tags: ['@E2E','@CashReplaceMultiGlassMobile', '@test_report', '@CASH'],
|
||||
tags: ['@E2E','@CashReplaceMultiGlassMobile', '@test_report', '@CASH', '@CASH-1182'],
|
||||
testData: cashReplaceMultiGlassMobileData
|
||||
};
|
||||
cashReplaceMultiGlassMobileTests.push(tc);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ const cashReplaceMultiGlassPromoInshopTests: ITestCase[] = [];
|
|||
|
||||
const tc = {
|
||||
name: `CashReplaceMultiGlassPromoInshop`,
|
||||
tags: ['@E2E','@CashReplaceMultiGlassPromoInshop', '@test_report', '@CASH', '@CASH-848'],
|
||||
tags: ['@E2E','@CashReplaceMultiGlassPromoInshop', '@test_report', '@CASH', '@CASH-1182'],
|
||||
testData: cashReplaceMultiGlassPromoInshopData
|
||||
};
|
||||
cashReplaceMultiGlassPromoInshopTests.push(tc);
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ const cashReplaceSafeliteCanNotRecalMobileTests: ITestCase[] = [];
|
|||
|
||||
const tc = {
|
||||
name: `CashReplaceSafeliteCanNotRecalMobile`,
|
||||
tags: ['@E2E','@CashReplaceSafeliteCanNotRecalMobile', '@test_report', '@CASH'],
|
||||
tags: ['@E2E','@CashReplaceSafeliteCanNotRecalMobile', '@test_report', '@CASH', '@CASH-1182'],
|
||||
testData: cashReplaceSafeliteCanNotRecalMobileData
|
||||
};
|
||||
cashReplaceSafeliteCanNotRecalMobileTests.push(tc);
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ const cashReplaceVinMobileTests: ITestCase[] = [];
|
|||
|
||||
const tc = {
|
||||
name: `CashReplaceVinMobile`,
|
||||
tags: ['@E2E','@CashReplaceVinMobile', '@test_report', '@CASH'],
|
||||
tags: ['@E2E','@CashReplaceVinMobile', '@test_report', '@CASH', '@CASH-1182'],
|
||||
testData: cashReplaceVinMobileData
|
||||
};
|
||||
cashReplaceVinMobileTests.push(tc);
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ body .headerlinecontainer .headerline1 {
|
|||
line-height: 32px;
|
||||
font-weight: 400;
|
||||
margin: 24px 0;
|
||||
text-align: center;
|
||||
text-align: left;
|
||||
}
|
||||
body input,
|
||||
body select {
|
||||
|
|
@ -137,9 +137,9 @@ body .buttonContainer {
|
|||
}
|
||||
body .buttonContainer button {
|
||||
position: relative;
|
||||
background: linear-gradient(270deg, #1574a1 0%, #003d58 100%);
|
||||
background: #db0020;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
border-radius: 50rem;
|
||||
color: #fff;
|
||||
justify-content: center;
|
||||
font-family: Urbanist, Arial, Helvetica, sans-serif;
|
||||
|
|
@ -149,7 +149,6 @@ body .buttonContainer button {
|
|||
}
|
||||
@media (hover: hover) {
|
||||
body .buttonContainer button {
|
||||
background: linear-gradient(270deg, #1574a1 0%, #003d58 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ body {
|
|||
line-height: 32px;
|
||||
font-weight: 400;
|
||||
margin: 24px 0;
|
||||
text-align: center;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -148,9 +148,9 @@ body {
|
|||
height: 48px;
|
||||
button {
|
||||
position: relative;
|
||||
background: linear-gradient(270deg, #1574a1 0%, #003d58 100%);
|
||||
background: #db0020;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
border-radius: 50rem;
|
||||
color: #fff;
|
||||
justify-content: center;
|
||||
font-family: Urbanist, Arial, Helvetica, sans-serif;
|
||||
|
|
@ -158,7 +158,6 @@ body {
|
|||
font-size: 16px;
|
||||
height: 48px;
|
||||
@media (hover: hover) {
|
||||
background: linear-gradient(270deg, #1574a1 0%, #003d58 100%);
|
||||
cursor: pointer;
|
||||
}
|
||||
&:focus {
|
||||
|
|
|
|||
|
|
@ -73,11 +73,11 @@ export const pageProgressMapper = {
|
|||
step: 3,
|
||||
},
|
||||
"payment-method": {
|
||||
percent: 92, //The first Step 4 must be 92 so the animated bar lines up with the dot
|
||||
step: 3,
|
||||
percent: 97, //The first Step 4 must be 97 so the animated bar lines up with the dot
|
||||
step: 4,
|
||||
},
|
||||
payment: {
|
||||
percent: 96,
|
||||
percent: 98.5,
|
||||
step: 4,
|
||||
},
|
||||
confirmation: {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,10 @@ https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Com
|
|||
<span class="fw-bold w-100" :class="[labelBold ? 'span-bold' : '']">
|
||||
{{ questionText }}
|
||||
</span>
|
||||
<p
|
||||
v-if="questionTextDescription"
|
||||
class="question-text-description"
|
||||
v-html="questionTextDescription"></p>
|
||||
</div>
|
||||
|
||||
<div class="w-100 d-flex justify-content-center">
|
||||
|
|
@ -60,6 +64,7 @@ https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Com
|
|||
:isInsuranceSelected="isInsuranceSelected"
|
||||
:suppressError="suppressError"
|
||||
:labelBold="labelBold"
|
||||
:isHidden="setIsHidden(index)"
|
||||
@buttonEvent="handleButtonEvent"
|
||||
v-model="selectedValues" />
|
||||
<!-- For nested questions -->
|
||||
|
|
@ -92,6 +97,11 @@ https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Com
|
|||
:name="formatString(groupName)"
|
||||
v-if="!suppressError"></error-message>
|
||||
</div>
|
||||
<div v-if="lazyLoad.isLazyLoad && !showAllButtons" id="show-more-button">
|
||||
<button class="btn btn-link" type="button" @click="toggleShowAllButtons">
|
||||
View more times
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -118,6 +128,7 @@ export default {
|
|||
isMultiSelect: Boolean,
|
||||
groupName: String,
|
||||
questionText: String,
|
||||
questionTextDescription: String,
|
||||
answers: Array,
|
||||
textPosition: {
|
||||
type: String,
|
||||
|
|
@ -158,6 +169,13 @@ export default {
|
|||
required: false,
|
||||
default: false,
|
||||
},
|
||||
lazyLoad: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
isLazyLoad: false,
|
||||
amountToLoad: null,
|
||||
}),
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
const propsClone = Object.assign({}, props);
|
||||
|
|
@ -189,6 +207,7 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
lastValuePushedToGa: null,
|
||||
showAllButtons: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -284,6 +303,15 @@ export default {
|
|||
this.$emit("update:modelValue", selectedAnswers);
|
||||
},
|
||||
},
|
||||
setIsHidden() {
|
||||
return (index) => {
|
||||
return (
|
||||
this.lazyLoad.isLazyLoad &&
|
||||
index >= this.lazyLoad.amountToLoad &&
|
||||
!this.showAllButtons
|
||||
);
|
||||
};
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
formatString(str) {
|
||||
|
|
@ -296,6 +324,9 @@ export default {
|
|||
const eventName = event.eventName;
|
||||
this.$emit(`buttonEvent.${eventName}`, event.args);
|
||||
},
|
||||
toggleShowAllButtons() {
|
||||
this.showAllButtons = true;
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
modelValue(newValue, oldValue) {
|
||||
|
|
@ -357,6 +388,28 @@ export default {
|
|||
font-family: UrbanistSemibold;
|
||||
color: $black;
|
||||
|
||||
&.timeslots {
|
||||
.col {
|
||||
& > label[isHidden="true"] {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
#show-more-button {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-top: 0.5rem;
|
||||
|
||||
button {
|
||||
color: $blue;
|
||||
text-underline-offset: 4px;
|
||||
|
||||
&:active {
|
||||
background: unset;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.radio-button-container {
|
||||
&:not(:last-child) {
|
||||
padding-bottom: map-get($spacers, 2);
|
||||
|
|
@ -376,6 +429,13 @@ export default {
|
|||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.question-text-description {
|
||||
font-family: UrbanistRegular;
|
||||
& > sup {
|
||||
font-size: 0.5rem;
|
||||
top: -0.4rem;
|
||||
}
|
||||
}
|
||||
.small-question-text {
|
||||
&.question-text {
|
||||
span {
|
||||
|
|
|
|||
|
|
@ -336,7 +336,7 @@ export default {
|
|||
);
|
||||
|
||||
if (this.estimatedServiceMinutesMinimum && this.estimatedServiceMinutesMaximum) {
|
||||
return `${inshopDurationTextWithoutTime} ${inshopDurationTime}`;
|
||||
return `${inshopDurationTextWithoutTime} <b>${inshopDurationTime}</b>`;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
@ -353,7 +353,7 @@ export default {
|
|||
);
|
||||
|
||||
if (this.estimatedServiceMinutesMinimum && this.estimatedServiceMinutesMaximum) {
|
||||
return `${mobileDurationTextWithoutTime} ${mobileDurationTime}`;
|
||||
return `${mobileDurationTextWithoutTime} <b>${mobileDurationTime}</b>`;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
@ -1025,6 +1025,8 @@ export default {
|
|||
flex-grow: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
text-align: left;
|
||||
|
||||
.duration-text-block {
|
||||
text-align: left;
|
||||
|
|
@ -1040,6 +1042,7 @@ export default {
|
|||
|
||||
.view-more-dates {
|
||||
color: $blue;
|
||||
font-family: UrbanistSemiBold;
|
||||
}
|
||||
}
|
||||
.loader {
|
||||
|
|
@ -1106,10 +1109,11 @@ export default {
|
|||
|
||||
.month-year {
|
||||
grid-area: 1 / 1 / 2 / 5;
|
||||
font-family: UrbanistBold;
|
||||
font-family: UrbanistSemiBold;
|
||||
color: $black;
|
||||
justify-content: center;
|
||||
justify-content: left;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
.legend {
|
||||
grid-area: 1 / 5 / 2 / 8;
|
||||
|
|
@ -1468,19 +1472,8 @@ export default {
|
|||
display: flex;
|
||||
max-width: 100%;
|
||||
flex-wrap: wrap;
|
||||
gap: 0 0.5rem;
|
||||
|
||||
& > div {
|
||||
flex: 0 0 calc(50% - 0.25rem);
|
||||
}
|
||||
}
|
||||
:deep(.button-question.is-mobile-appointment) {
|
||||
.button-inner-wrapper > div {
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
}
|
||||
:deep(.button-question.is-drop-off-appointment) {
|
||||
.button-inner-wrapper > div {
|
||||
flex: 0 0 100%;
|
||||
}
|
||||
}
|
||||
|
|
@ -1490,6 +1483,8 @@ export default {
|
|||
display: block;
|
||||
position: relative;
|
||||
height: 2rem;
|
||||
font-size: 0.875rem;
|
||||
padding-top: 0;
|
||||
width: 100%;
|
||||
justify-content: center;
|
||||
background: transparent;
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@
|
|||
:validationRules="validationRules"
|
||||
:placeHolderText="placeHolderText"
|
||||
:valueAsKey="valueAsKey">
|
||||
<option v-if="placeHolderText" value="" selected>{{ placeHolderText }}</option>
|
||||
<option v-if="placeHolderText && !isDisabled" value="" selected>
|
||||
{{ placeHolderText }}
|
||||
</option>
|
||||
<option
|
||||
v-for="(value, name, index) in options"
|
||||
:value="valueAsKey == true ? value : name"
|
||||
|
|
@ -152,7 +154,7 @@ export default {
|
|||
border: 1px solid $gray-500;
|
||||
border-radius: 0.5rem;
|
||||
min-height: 3rem;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
@include media-breakpoint-up(md) {
|
||||
min-height: 3.5rem;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,7 +9,9 @@
|
|||
tabindex="-1"
|
||||
aria-labelledby="ModalComponentLabel"
|
||||
@keypress.enter="onEnter"
|
||||
aria-hidden="true">
|
||||
aria-hidden="true"
|
||||
@click.self="closeModal">
|
||||
<!--Close modal when clicking other than close button-->
|
||||
<div class="modal-dialog modal-dialog-centered">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header mb-0 mt-6">
|
||||
|
|
@ -248,6 +250,7 @@ export default {
|
|||
|
||||
button {
|
||||
margin: 0;
|
||||
border-radius: 50rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -337,7 +337,7 @@ export default {
|
|||
border-radius: 0.5rem;
|
||||
min-height: 3rem;
|
||||
padding: 0.75rem 1rem;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
@include media-breakpoint-up(md) {
|
||||
padding: 1rem;
|
||||
min-height: 3.5rem;
|
||||
|
|
|
|||
|
|
@ -227,9 +227,14 @@ export default {
|
|||
}
|
||||
}
|
||||
|
||||
&.has-package-discount {
|
||||
//Package container height with package discount AND "most popular" label
|
||||
&.has-package-discount.has-subheader {
|
||||
min-height: 170px;
|
||||
}
|
||||
//Package container height with package discount only
|
||||
&.has-package-discount {
|
||||
min-height: 136px;
|
||||
}
|
||||
|
||||
&:before {
|
||||
content: "";
|
||||
|
|
|
|||
|
|
@ -15,7 +15,9 @@
|
|||
v-show="shouldShowWebchatButton"
|
||||
v-on:click="webchatClicked"
|
||||
type="button"
|
||||
class="chat-button"></button>
|
||||
class="chat-button">
|
||||
<span>Chat Now</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
<div class="button-container">
|
||||
|
|
@ -206,14 +208,11 @@ export default {
|
|||
}
|
||||
}
|
||||
position: relative;
|
||||
padding: 0 0 1rem 0;
|
||||
padding: 0;
|
||||
|
||||
.button-container {
|
||||
&.webchat {
|
||||
margin-right: 1rem;
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-right: 2rem;
|
||||
}
|
||||
margin-right: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -232,14 +231,29 @@ export default {
|
|||
|
||||
.webchat {
|
||||
.chat-button {
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
text-transform: uppercase;
|
||||
width: 7.5rem;
|
||||
height: 2rem;
|
||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' xml:space='preserve' id='Layer_2' x='0' y='0' style='enable-background:new 0 0 24 24' version='1.1' viewBox='0 0 24 24'%3E%3Cstyle%3E .st0%7Bfill:%232e6fb6%7D %3C/style%3E%3Ccircle cx='12' cy='12' r='12' class='st0'/%3E%3Cpath d='M18.3 12c0 3.5-2.8 6.3-6.3 6.3-1.2 0-2.4-.4-3.4-1l-2.3.7s-.5.1-.3-.4.5-1.7.7-2.2c-.6-1-1-2.1-1-3.3 0-3.5 2.8-6.3 6.3-6.3 3.5-.1 6.3 2.7 6.3 6.2z' style='fill:%23fff'/%3E%3Ccircle cx='10.2' cy='12' r='.6' class='st0'/%3E%3Ccircle cx='12' cy='12' r='.6' class='st0'/%3E%3Ccircle cx='13.8' cy='12' r='.6' class='st0'/%3E%3C/svg%3E");
|
||||
background-repeat: no-repeat;
|
||||
background-size: 1.5rem 1.5rem;
|
||||
background-position: center;
|
||||
background-size: 2rem 2rem;
|
||||
background-position: right;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
padding-right: 2rem;
|
||||
font-size: 0.875rem;
|
||||
font-weight: 600;
|
||||
font-family: "UrbanistSemibold";
|
||||
color: $blue;
|
||||
@include media-breakpoint-down(md) {
|
||||
width: 2rem;
|
||||
padding-right: 0;
|
||||
}
|
||||
span {
|
||||
@include media-breakpoint-down(md) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,25 +39,14 @@
|
|||
<span class="dot4"></span>
|
||||
</div>
|
||||
<div class="d-flex flex-column justify-content-between">
|
||||
<div class="step-containers">
|
||||
<span class="step-number">Step 1 of 4</span>
|
||||
<div class="step-containers" v-for="step in steps" :key="step.number">
|
||||
<span class="step-number">Step {{ step.number }} of 4</span>
|
||||
<br />
|
||||
<span class="step-name">Vehicle</span>
|
||||
</div>
|
||||
<div class="step-containers">
|
||||
<span class="step-number">Step 2 of 4</span>
|
||||
<br />
|
||||
<span class="step-name">Quote</span>
|
||||
</div>
|
||||
<div class="step-containers">
|
||||
<span class="step-number">Step 3 of 4</span>
|
||||
<br />
|
||||
<span class="step-name">Schedule</span>
|
||||
</div>
|
||||
<div class="step-containers">
|
||||
<span class="step-number">Step 4 of 4</span>
|
||||
<br />
|
||||
<span class="step-name">Review</span>
|
||||
<span
|
||||
class="step-name"
|
||||
:class="{ 'active-step': step.number === currentStepNumber }">
|
||||
{{ step.name }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -107,6 +96,14 @@ export default {
|
|||
currentStepNumber() {
|
||||
return getProgressBarStep(this.$route.name);
|
||||
},
|
||||
steps() {
|
||||
return [
|
||||
{ number: 1, name: "Vehicle" },
|
||||
{ number: 2, name: "Quote" },
|
||||
{ number: 3, name: "Schedule" },
|
||||
{ number: 4, name: "Review" },
|
||||
];
|
||||
},
|
||||
},
|
||||
components: {
|
||||
progressBar,
|
||||
|
|
@ -118,11 +115,15 @@ export default {
|
|||
.menu-modal-container {
|
||||
button {
|
||||
border: none;
|
||||
color: $blue;
|
||||
font-family: UrbanistSemibold, Arial, Helvetica, sans-serif;
|
||||
font-weight: 600;
|
||||
font-size: 0.875rem;
|
||||
&.menu-button {
|
||||
width: auto;
|
||||
height: auto;
|
||||
border-radius: 1.5rem;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
background-color: $white;
|
||||
position: relative;
|
||||
display: flex;
|
||||
|
|
@ -254,6 +255,10 @@ export default {
|
|||
.step-name {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
.active-step {
|
||||
font-family: UrbanistSemibold, Arial, Helvetica, sans-serif;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
.modal-fullscreen {
|
||||
|
|
|
|||
|
|
@ -125,7 +125,7 @@ export default {
|
|||
align-items: center;
|
||||
height: 3rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
&.progress-saved {
|
||||
background: none;
|
||||
|
|
|
|||
|
|
@ -9,79 +9,11 @@
|
|||
<img :src="ScheduleConfirmationImage" />
|
||||
<span v-html="ScheduleConfirmationText"></span>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-6 col-xl-4">
|
||||
<div class="header-container">
|
||||
<img :src="ScheduleConfirmationImage" />
|
||||
<span v-html="ScheduleConfirmationText"></span>
|
||||
</div>
|
||||
|
||||
<div class="emailtext" v-html="ConfirmationEmailText"></div>
|
||||
|
||||
<div class="main">
|
||||
<div></div>
|
||||
|
||||
<div class="scheduleText">
|
||||
<p>{{ ScheduleDateFormatted }}</p>
|
||||
<p>{{ ScheduleTimeFormatted }}</p>
|
||||
</div>
|
||||
|
||||
<addToCalendar
|
||||
mobileWidgetName="AddToCalendar_Mobile"
|
||||
inShopWidgetName="AddToCalendar_InShop"
|
||||
dropOffWidgetName="AddToCalendar_DropOff"
|
||||
overnightDropOffWidgetName="AddToCalendar_OvernightDropOff"
|
||||
allDayDropOffWidgetName="AddToCalendar_AllDayDropOff"
|
||||
sameDayDropOffWidgetName="AddToCalendar_SameDayDropOff"
|
||||
:serviceLocationFullAddress="ServiceLocationFullAddress"
|
||||
:providerFullAddress="ProviderFullAddress"
|
||||
:appointmentType="AppointmentType"
|
||||
:scheduleDate="ScheduleDate"
|
||||
:scheduleStartTime="ScheduleStartTime"
|
||||
:scheduleEndTime="ScheduleEndTime" />
|
||||
|
||||
<div class="appointment-text" v-html="AppointmentWordingText"></div>
|
||||
|
||||
<textBlock
|
||||
:customText="AppointmentDuration"
|
||||
justifyText="center"
|
||||
typeStyle="medium"
|
||||
class="duration-text-block" />
|
||||
</div>
|
||||
|
||||
<div class="mt-3" v-if="shouldDisplayFosterLove">
|
||||
<donationBlock
|
||||
cmsWidgetName="DonationWidget"
|
||||
v-model="donationAmount"
|
||||
:donationValues="donationValues"
|
||||
:showDonationSuccess="showDonationSuccess"
|
||||
:showDonationError="showDonationError"
|
||||
@DonationAddedEvent="addDonationToOrder"
|
||||
ref="donationBlock" />
|
||||
</div>
|
||||
|
||||
<hr class="mt-4 mb-0" />
|
||||
|
||||
<cart
|
||||
v-if="ShowCart"
|
||||
:damage="damageInfo"
|
||||
:availableVaps="vaps"
|
||||
:allowItemRemoval="false"
|
||||
v-model="lineItemsWithoutDonation"
|
||||
:donationCartItem="donationLineItem"
|
||||
:showAsPaid="isPia"
|
||||
servicePackageOptionsCmsName="ServicePackageTitle"
|
||||
:isInsurance="isInsurance"
|
||||
:insuranceDeductible="currentDeductible"
|
||||
:insuranceCompanyName="insuranceCompanyName"
|
||||
:showInsuranceCoverageAs="showInsuranceCoverageAs"
|
||||
:shouldHideRecalibration="shouldHideRecalibration"
|
||||
:isExpandedOnLoad="false"
|
||||
:isItac="isItac"
|
||||
:isNoComp="isNoComp"
|
||||
:isMSRFeeApplicable="isMSRFeeApplicable" />
|
||||
|
||||
<hr class="mb-5" />
|
||||
<div class="emailtext" v-html="ConfirmationEmailText"></div>
|
||||
<div class="main">
|
||||
<div class="scheduleText">
|
||||
<p>{{ ScheduleDateFormatted }}</p>
|
||||
<p>{{ ScheduleTimeFormatted }}</p>
|
||||
</div>
|
||||
|
||||
<addToCalendar
|
||||
|
|
@ -118,7 +50,7 @@
|
|||
ref="donationBlock" />
|
||||
</div>
|
||||
|
||||
<hr class="mt-5 mb-0" />
|
||||
<hr class="mt-4 mb-0" />
|
||||
|
||||
<cart
|
||||
v-if="ShowCart"
|
||||
|
|
@ -139,7 +71,7 @@
|
|||
:isNoComp="isNoComp"
|
||||
:isMSRFeeApplicable="isMSRFeeApplicable" />
|
||||
|
||||
<hr class="mt-4 mb-5" />
|
||||
<hr class="mb-5" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -108,11 +108,11 @@ export default {
|
|||
position: relative;
|
||||
background: $white;
|
||||
transition: all 150ms linear;
|
||||
border-radius: $border-radius-lg;
|
||||
border-radius: 50rem;
|
||||
border: 1px solid $gray-500;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
span {
|
||||
&.small {
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@
|
|||
alertClass="alert-info" />
|
||||
|
||||
<promoModalQuestion
|
||||
class="mt-6 d-flex justify-content-center"
|
||||
class="mt-6 d-flex"
|
||||
v-model="lineItems"
|
||||
:addableVaps="addableVaps"
|
||||
pageName="quote"
|
||||
|
|
@ -624,7 +624,7 @@ export default {
|
|||
if (this.packageNumber > 2) {
|
||||
return "col-xl-12";
|
||||
} else {
|
||||
return "col-xl-6";
|
||||
return "col-xl-10";
|
||||
}
|
||||
},
|
||||
currentNumberOfPackagesAction(packageNumber) {
|
||||
|
|
@ -922,6 +922,60 @@ export default {
|
|||
width: -moz-available;
|
||||
}
|
||||
}
|
||||
.promo-modal-question {
|
||||
@include media-breakpoint-up(md) {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
//Save email modal ONLY centered on screen for quote page only
|
||||
.save-progress-popup-question {
|
||||
:deep(.modal-component) {
|
||||
.modal-dialog {
|
||||
max-width: 767px;
|
||||
margin: 0 0.5rem;
|
||||
top: 0;
|
||||
@include media-breakpoint-up(md) {
|
||||
width: 50%;
|
||||
max-width: 600px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
transform: none;
|
||||
margin: 0 auto;
|
||||
}
|
||||
.modal-content {
|
||||
border-radius: 0.5rem;
|
||||
margin: 0.5rem 0 0 0;
|
||||
@include media-breakpoint-up(md) {
|
||||
box-shadow: none;
|
||||
border-radius: 0;
|
||||
height: auto;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
&.modal-dialog-centered {
|
||||
height: auto;
|
||||
min-height: auto;
|
||||
}
|
||||
}
|
||||
.modal-footer {
|
||||
button {
|
||||
&.btn {
|
||||
border-radius: 50rem;
|
||||
}
|
||||
}
|
||||
button {
|
||||
&.btn {
|
||||
&.skip-button {
|
||||
margin: 0 auto 1rem;
|
||||
color: $blue;
|
||||
font-family: UrbanistSemibold, Arial, Helvetica, sans-serif;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.quote-page.show-save-progress-popup .row.justify-content-center {
|
||||
display: none;
|
||||
|
|
|
|||
|
|
@ -5,56 +5,9 @@
|
|||
<div class="container page-container-grouped-styles">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-4" />
|
||||
<serviceZipModalQuestion
|
||||
editScreenReaderTextCmsWidgetName="ScreenReaderZipEditWidget"
|
||||
v-model="serviceZipCodeQuestion"
|
||||
ref="serviceZipCodeQuestion"
|
||||
:carId="carId"
|
||||
:isVehicleHeavyTruck="isVehicleHeavyTruck"
|
||||
:mobileFeePart="mobileFeePart"
|
||||
@updated-mobile-fee-part="setMobileFeePart"
|
||||
@updated-recycle-fee-part="setRecycleFeePart"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
@updated-contains-military-base="setContainsMilitaryBase"
|
||||
@updated-bill-to-account-number="setBillToAccountNumber"
|
||||
@service-zip-changed-from-modal="onServiceZipChanged"
|
||||
linkWidgetName="ServiceZipLinkWidget"
|
||||
modalWidgetName="ServiceZipModalWidget" />
|
||||
<alert
|
||||
ref="alertMilitaryBaseZip"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
||||
v-if="displayMilitaryZipAlert"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertMobileOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMobileOnlyWidget"
|
||||
v-if="displayServiceableMobileOnly"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertRecalNoMobile"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||
v-if="displayRecalibrationWarning"
|
||||
@text-link-clicked="openModalAction"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertInshopOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertInshopOnlyWidget"
|
||||
v-if="displayServiceableInshopOnly"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertNoShops"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertNoShopsWidget"
|
||||
v-if="displayNoShopsAlert"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertMobileFeeFree"
|
||||
class="my-5"
|
||||
class="mb-5"
|
||||
cmsWidgetName="AlertMobileFeeFreeWidget"
|
||||
v-if="showMobileFreeAlert"
|
||||
alertClass="alert-success" />
|
||||
|
|
@ -62,6 +15,7 @@
|
|||
</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" />
|
||||
<appointmentTypeQuestion
|
||||
v-model="appointmentTypeFromAppointmentTypeQuestion"
|
||||
v-show="isAppointmentTypeDisplayed"
|
||||
|
|
@ -77,21 +31,78 @@
|
|||
labelBold="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<alert
|
||||
ref="alertMobileOnly"
|
||||
class="mt-5 mb-5"
|
||||
cmsWidgetName="AlertMobileOnlyWidget"
|
||||
v-if="displayServiceableMobileOnly"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertRecalNoMobile"
|
||||
class="mt-5 mb-5"
|
||||
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||
v-if="displayRecalibrationWarning"
|
||||
@text-link-clicked="openModalAction"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertInshopOnly"
|
||||
class="mt-5 mb-5"
|
||||
cmsWidgetName="AlertInshopOnlyWidget"
|
||||
v-if="displayServiceableInshopOnly"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertMilitaryBaseZip"
|
||||
class="mt-5 mb-5"
|
||||
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
||||
v-if="displayMilitaryZipAlert"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
ref="alertNoShops"
|
||||
class="mt-5 mb-5"
|
||||
cmsWidgetName="AlertNoShopsWidget"
|
||||
v-if="displayNoShopsAlert"
|
||||
alertClass="alert-warning" />
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="appointmentType && appointmentType === appointmentTypeStrings.MOBILE"
|
||||
class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mt-4" />
|
||||
<serviceZipModalQuestion
|
||||
editScreenReaderTextCmsWidgetName="ScreenReaderZipEditWidget"
|
||||
v-model="serviceZipCodeQuestion"
|
||||
ref="serviceZipCodeQuestion"
|
||||
:carId="carId"
|
||||
:isVehicleHeavyTruck="isVehicleHeavyTruck"
|
||||
:mobileFeePart="mobileFeePart"
|
||||
@updated-mobile-fee-part="setMobileFeePart"
|
||||
@updated-recycle-fee-part="setRecycleFeePart"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
@updated-contains-military-base="setContainsMilitaryBase"
|
||||
@updated-bill-to-account-number="setBillToAccountNumber"
|
||||
@service-zip-changed-from-modal="onServiceZipChanged"
|
||||
linkWidgetName="ServiceZipLinkWidget"
|
||||
modalWidgetName="ServiceZipModalWidget" />
|
||||
</div>
|
||||
<div
|
||||
class="row your-shop-location"
|
||||
v-if="appointmentType && appointmentType !== appointmentTypeStrings.MOBILE">
|
||||
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<button-question
|
||||
class="shop-question-button"
|
||||
ref="buttonQuestion"
|
||||
:answers="selectedShopAnswer"
|
||||
:modelValue="selectedProvider?.providerNumber"
|
||||
:isMultiSelect="false"
|
||||
:readonly="true"
|
||||
:questionText="questionText"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
groupName="chooseShop" />
|
||||
<div>
|
||||
<shopLocation
|
||||
v-if="
|
||||
appointmentType && appointmentType !== appointmentTypeStrings.MOBILE
|
||||
"
|
||||
:selectedShop="selectedShopAnswer"
|
||||
:selectedProviderNumberFromParent="selectedProvider?.providerNumber"
|
||||
:shopProviderDataFromParent="shopProviderData"
|
||||
:zipCodeFromParent="zipCode"
|
||||
:isShopQuestionDisplayed="isShopQuestionDisplayed"
|
||||
@shop-selected="onShopSelected"
|
||||
@updated-serviceability="setServiceabilityDetails" />
|
||||
</div>
|
||||
<div>
|
||||
<textBlock
|
||||
v-if="mobileFeeApplies && isMobileSelected"
|
||||
|
|
@ -100,14 +111,6 @@
|
|||
typeStyle="caption"
|
||||
class="ps-4 pe-4 mt-4" />
|
||||
</div>
|
||||
<shopQuestionPopup
|
||||
v-if="isShopQuestionDisplayed"
|
||||
:selectedProviderNumberFromParent="selectedProvider?.providerNumber"
|
||||
:shopProviderDataFromParent="shopProviderData"
|
||||
@shop-selected="onShopSelected"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
:zipCodeFromParent="zipCode"
|
||||
cmsWidgetName="YourSafeliteShopWidget" />
|
||||
|
||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||
</div>
|
||||
|
|
@ -158,9 +161,8 @@ 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 shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup";
|
||||
import buttonQuestion from "@/digital-components/button-question/button-question.vue";
|
||||
import shopListButton from "@/layouts/service-location/shop-question/shop-list-button/shop-list-button";
|
||||
import shopLocation from "@/layouts/schedule/shop-location/shop-location";
|
||||
|
||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||
import navbar from "@/fmg-components/nav-bar/nav-bar";
|
||||
|
|
@ -697,7 +699,12 @@ export default {
|
|||
);
|
||||
},
|
||||
isAppointmentTypeDisplayed() {
|
||||
return this.zipCode && !this.displayNoShopsAlert;
|
||||
return (
|
||||
this.zipCode &&
|
||||
!this.displayNoShopsAlert &&
|
||||
this.isServiceableMobile &&
|
||||
this.isServiceableInshop
|
||||
);
|
||||
},
|
||||
requiresInshopRecalibration() {
|
||||
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
|
||||
|
|
@ -769,21 +776,15 @@ export default {
|
|||
const zipCode = this.selectedProvider.address.zipCode;
|
||||
const distanceInMiles = provider ? Math.round(provider.distanceInMiles * 2) / 2 : 0;
|
||||
|
||||
return [
|
||||
{
|
||||
buttonLabel: `${city}`,
|
||||
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
||||
buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
|
||||
additionalButtonData: this.additionalButtonData,
|
||||
value: this.selectedProvider.providerNumber,
|
||||
},
|
||||
];
|
||||
return {
|
||||
city: `${city}`,
|
||||
distance: `${distanceInMiles} mi`,
|
||||
address1: `${streetAddress}`,
|
||||
address2: `${city}, ${state} ${zipCode}`,
|
||||
};
|
||||
}
|
||||
return [];
|
||||
},
|
||||
questionText() {
|
||||
return this.getCmsContent("YourSafeliteShopWidget", "QuestionText");
|
||||
},
|
||||
appointmentTypeStrings() {
|
||||
return AppointmentTypeStrings;
|
||||
},
|
||||
|
|
@ -1554,6 +1555,7 @@ export default {
|
|||
}
|
||||
},
|
||||
updateTimeSlot(timeSlotObj) {
|
||||
if (this.preSelectedDate && !timeSlotObj?.timeSlot?.date) return;
|
||||
this.selectedTimeSlotInfo = timeSlotObj;
|
||||
if (
|
||||
this.appointmentType !== AppointmentTypeStrings.MOBILE &&
|
||||
|
|
@ -1740,57 +1742,75 @@ export default {
|
|||
serviceZipModalQuestion,
|
||||
appointmentTypeQuestion,
|
||||
contentGroupModal,
|
||||
shopQuestionPopup,
|
||||
buttonQuestion,
|
||||
shopLocation,
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
.container {
|
||||
&.page-schedule {
|
||||
padding: 0 1rem;
|
||||
.text-link-small {
|
||||
a,
|
||||
.btn-link {
|
||||
width: auto;
|
||||
margin: 0 auto;
|
||||
height: auto;
|
||||
font-size: 0.875rem;
|
||||
line-height: 1.75;
|
||||
padding: 0;
|
||||
border-radius: 0;
|
||||
&:focus {
|
||||
outline: 1px solid $blue;
|
||||
}
|
||||
@include media-breakpoint-up(md) {
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
.question-text {
|
||||
margin-bottom: 1.5rem;
|
||||
|
||||
& > span {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
.funnel-sub-header {
|
||||
h5.dark-header {
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
}
|
||||
.change-location a {
|
||||
font-family: UrbanistSemibold;
|
||||
}
|
||||
.date-picker {
|
||||
border-top: 1px solid $gray-500;
|
||||
margin-top: 1.5rem;
|
||||
}
|
||||
.time-slots-question {
|
||||
padding: 0 0.75rem;
|
||||
}
|
||||
}
|
||||
.question-text > span {
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
}
|
||||
.alert.alert-warning {
|
||||
.alert-heading {
|
||||
color: $black;
|
||||
font-family: UrbanistSemibold;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.shop-question-button .list-button-content {
|
||||
background: $blue-100;
|
||||
box-shadow: 0 0 0 1px $primary;
|
||||
}
|
||||
|
||||
.container .row .col-12 .alert-success .alert-heading {
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.funnel-sub-header h5 {
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
font-family: UrbanistSemibold;
|
||||
span {
|
||||
letter-spacing: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.appointment-type .funnel-sub-header h5 {
|
||||
font-family: UrbanistRegular;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
.funnel-sub-header.my-5 h5 {
|
||||
font-weight: 400;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
:deep(.funnel-sub-header:not(.mb-5)) {
|
||||
h5.dark-header {
|
||||
font-weight: 600;
|
||||
font-size: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.col-12 a {
|
||||
font-family: UrbanistSemibold;
|
||||
font-weight: 500;
|
||||
line-height: 26px;
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
|
||||
.text-block.duration-text-block b {
|
||||
font-family: UrbanistSemibold;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
121
src/layouts/schedule/shop-location/shop-location.vue
Normal file
121
src/layouts/schedule/shop-location/shop-location.vue
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
<template>
|
||||
<div id="shop-location">
|
||||
<textBlock :customText="questionText" typeStyle="button-question" class="mb-2" />
|
||||
<div>
|
||||
<div>
|
||||
<label v-for="addressItem in addressDetails" :key="addressItem">
|
||||
{{ addressItem }}
|
||||
</label>
|
||||
</div>
|
||||
<div>
|
||||
<label>{{ selectedShop.distance }}</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<shopQuestionPopup
|
||||
v-if="isShopQuestionDisplayed"
|
||||
:selectedProviderNumberFromParent="selectedProviderNumberFromParent"
|
||||
:shopProviderDataFromParent="shopProviderDataFromParent"
|
||||
:zipCodeFromParent="zipCodeFromParent"
|
||||
@shop-selected="onShopSelected"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
cmsWidgetName="YourSafeliteShopWidget" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import textBlock from "@/digital-components/text-block/text-block";
|
||||
import shopQuestionPopup from "@/layouts/service-location/shop-question/shop-question-popup";
|
||||
|
||||
export default {
|
||||
name: "shopLocation",
|
||||
props: {
|
||||
selectedShop: {
|
||||
type: Object,
|
||||
default: () => ({
|
||||
city: null,
|
||||
distance: null,
|
||||
address1: null,
|
||||
address2: null,
|
||||
}),
|
||||
},
|
||||
isShopQuestionDisplayed: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
selectedProviderNumberFromParent: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
shopProviderDataFromParent: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
zipCodeFromParent: {
|
||||
type: String,
|
||||
default: null,
|
||||
},
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent("YourSafeliteShopWidget", "QuestionText");
|
||||
},
|
||||
addressDetails() {
|
||||
const { distance, ...addressDetails } = this.selectedShop;
|
||||
return addressDetails;
|
||||
},
|
||||
},
|
||||
components: {
|
||||
textBlock,
|
||||
shopQuestionPopup,
|
||||
},
|
||||
methods: {
|
||||
onShopSelected(shopQuestionPopUpData) {
|
||||
this.$emit("shop-selected", shopQuestionPopUpData);
|
||||
},
|
||||
setServiceabilityDetails(serviceabilityDetails) {
|
||||
this.$emit("updated-serviceability", serviceabilityDetails);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
#shop-location {
|
||||
& > div {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
& > div {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
label {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > div.shop-question {
|
||||
width: 172px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
#shop-location {
|
||||
& > div.shop-question {
|
||||
width: fit-content;
|
||||
background-color: $blue;
|
||||
border-radius: $border-radius-pill;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
color: $white;
|
||||
font-weight: $font-weight-600;
|
||||
line-height: 1.5rem;
|
||||
padding: 0.75rem 3rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -90,11 +90,11 @@ export default {
|
|||
position: relative;
|
||||
background: $white;
|
||||
transition: all 150ms linear;
|
||||
border-radius: $border-radius-lg;
|
||||
border-radius: $border-radius-pill;
|
||||
border: 1px solid $gray-500;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
span.premium-appointment-price {
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -601,7 +601,7 @@ export default {
|
|||
}
|
||||
}
|
||||
.waitlist {
|
||||
box-shadow: 0px 1px 4px 0px #00000033;
|
||||
box-shadow: 0 1px 5px 0 #00000033;
|
||||
border-radius: 8px;
|
||||
font-size: $h6-font-size;
|
||||
padding: 16px;
|
||||
|
|
@ -611,7 +611,7 @@ export default {
|
|||
padding-left: 0px;
|
||||
input {
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 1px 4px 0px #00000033;
|
||||
box-shadow: 0 1px 5px 0 #00000033;
|
||||
}
|
||||
}
|
||||
.form-check-input {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,12 @@
|
|||
v-if="isDropOffAppointmentAvailable"
|
||||
v-model="selectedAnswerForDropOffOrInshop"
|
||||
:questionText="dropOffOrPickATimeQuestionLabelText"
|
||||
:questionTextDescription="dropOffOrPickATimeQuestionDescription"
|
||||
:answers="answersForDropOffQuestion"
|
||||
isRequired
|
||||
insertOrLabelBeforeFinalOption
|
||||
groupName="chooseDropOffOrInshop"
|
||||
class="choose-dropoff-or-inshop"
|
||||
validationRules="time-slot-required">
|
||||
<div>
|
||||
<alert
|
||||
|
|
@ -30,6 +32,7 @@
|
|||
isInshopOrDropOffAppointment ? 'is-inshop-or-drop-off-appointment' : '',
|
||||
]"
|
||||
:answers="availableTimeSlots"
|
||||
:lazyLoad="{ isLazyLoad: !isMobileAppointment, amountToLoad: 10 }"
|
||||
groupName="chooseTimeSlot"
|
||||
textPosition="text-center"
|
||||
v-model="selectedAnswerForTimeSlots"
|
||||
|
|
@ -47,6 +50,7 @@
|
|||
cmsWidgetName="WaitListLabelWidget"
|
||||
typeStyle="medium"
|
||||
fontWeight="600"
|
||||
class="waitlist-label"
|
||||
marginTopSizeOverride="0" />
|
||||
<checkboxQuestion
|
||||
class="mt-3"
|
||||
|
|
@ -190,7 +194,8 @@ export default {
|
|||
this.selectedDate == null ||
|
||||
this.appointmentType === AppointmentTypeStrings.IN_SHOP_OR_DROP_OFF ||
|
||||
this.appointmentType === AppointmentTypeStrings.IN_SHOP ||
|
||||
this.appointmentType === AppointmentTypeStrings.DROP_OFF
|
||||
this.appointmentType === AppointmentTypeStrings.DROP_OFF ||
|
||||
!this.availableTimeSlots
|
||||
) {
|
||||
if (!this.selectedAnswerForTimeSlots && !this.selectedAnswerForDropOffOrInshop) {
|
||||
this.autoSelectTimeSlotIfOnlyOneIsAvailable();
|
||||
|
|
@ -228,6 +233,10 @@ export default {
|
|||
dropOffOrPickATimeQuestionLabelText() {
|
||||
return this.getCmsContent(this.dropOffOrPickATimeQuestionCmsWidgetName, "QuestionText");
|
||||
},
|
||||
dropOffOrPickATimeQuestionDescription() {
|
||||
// This is hardcoded because Input Question Widget doesn't currently have a place to add additional text
|
||||
return "You can drop off your vehicle in the morning and pick it up later in the day with Drop & Go<sup>™</sup> or pick an appointment time.";
|
||||
},
|
||||
pickATimeButtonLabelText() {
|
||||
return this.getCmsContent(this.dropOffOrPickATimeQuestionCmsWidgetName, "Answers")[0]
|
||||
.Text;
|
||||
|
|
@ -644,18 +653,31 @@ export default {
|
|||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
.button-question.choose-dropoff-or-inshop
|
||||
.button-inner-wrapper
|
||||
.col:first-child
|
||||
.button-content.list-button-content
|
||||
> span::after {
|
||||
content: "TM";
|
||||
vertical-align: super;
|
||||
font-size: 50%;
|
||||
}
|
||||
.waitlist {
|
||||
box-shadow: 0px 1px 4px 0px #00000033;
|
||||
box-shadow: 0 1px 5px 0 #00000033;
|
||||
border-radius: 8px;
|
||||
font-size: 1rem;
|
||||
padding: 16px;
|
||||
text-align: left;
|
||||
|
||||
.waitlist-label {
|
||||
font-family: UrbanistSemibold;
|
||||
}
|
||||
|
||||
.ui-checkbox {
|
||||
padding-left: 0px;
|
||||
input {
|
||||
border-radius: 4px;
|
||||
box-shadow: 0px 1px 4px 0px #00000033;
|
||||
box-shadow: 0 1px 5px 0 #00000033;
|
||||
}
|
||||
}
|
||||
.form-check-input {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
:questionText="questionText"
|
||||
:answers="answersToDisplay"
|
||||
:groupName="groupName"
|
||||
buttonTypeString="listCard"
|
||||
v-model="selectedValue"
|
||||
:suppressError="suppressError"
|
||||
:validationRules="validationRules"
|
||||
|
|
@ -134,4 +133,11 @@ export default {
|
|||
width: auto;
|
||||
}
|
||||
}
|
||||
div.appointment-type-question div.button-question div.col div.button-content {
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
}
|
||||
div.appointment-type-question div.button-question div.question-text span {
|
||||
font-weight: 500;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -214,14 +214,19 @@ export default {
|
|||
);
|
||||
|
||||
// update content related to service zip code
|
||||
this.$emit("updated-mobile-fee-part", mobileFeePart);
|
||||
this.$emit("updated-recycle-fee-part", recycleFeePart);
|
||||
this.$emit("updated-serviceability", serviceabilityDetails.data);
|
||||
this.$emit("updated-contains-military-base", zipCodeData.containsMilitaryBase);
|
||||
this.$emit("updated-bill-to-account-number", billToAccountNumber);
|
||||
this.$emit("service-zip-changed-from-modal");
|
||||
// update the page level model
|
||||
this.$emit("update:modelValue", this.internalModel);
|
||||
if (this.internalModel.zipCode !== this.modelValue.zipCode) {
|
||||
this.$emit("updated-mobile-fee-part", mobileFeePart);
|
||||
this.$emit("updated-recycle-fee-part", recycleFeePart);
|
||||
this.$emit("updated-serviceability", serviceabilityDetails.data);
|
||||
this.$emit(
|
||||
"updated-contains-military-base",
|
||||
zipCodeData.containsMilitaryBase
|
||||
);
|
||||
this.$emit("updated-bill-to-account-number", billToAccountNumber);
|
||||
this.$emit("service-zip-changed-from-modal");
|
||||
// update the page level model
|
||||
this.$emit("update:modelValue", this.internalModel);
|
||||
}
|
||||
|
||||
this.closeModal();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ export default {
|
|||
border: 1px solid $gray-500;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
span {
|
||||
&.small {
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||
<div class="container">
|
||||
<div class="container vehicle-damage">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mb-7" />
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="mb-4" />
|
||||
<alert
|
||||
ref="vehicleChangeAlert"
|
||||
v-if="shouldDisplayVehicleChangeAlert"
|
||||
|
|
@ -755,11 +755,31 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.replace-options-question {
|
||||
.vehicle-damage {
|
||||
.base-input-button:not(.has-error):hover.list-card:not(.selected) {
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
.question-text {
|
||||
margin: 1rem 0 0 0;
|
||||
margin: 1.5rem 0 0.5rem 0;
|
||||
}
|
||||
}
|
||||
.replace-options-question {
|
||||
.base-input-button:not(.has-error):hover.list-card:not(.selected) {
|
||||
border-radius: 50rem;
|
||||
}
|
||||
.button-question {
|
||||
label {
|
||||
&.list-card,
|
||||
&.list-card input[type="checkbox"]:checked + .list-card-content,
|
||||
&.list-card input[type="radio"]:checked + .list-card-content {
|
||||
border-radius: 50rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.question-text {
|
||||
margin: 1.5rem 0 0.5rem 0;
|
||||
@include media-breakpoint-up(md) {
|
||||
margin: 1rem 0;
|
||||
margin: 1.5rem 0 0.5rem 0;
|
||||
}
|
||||
}
|
||||
.two-list-card-width {
|
||||
|
|
|
|||
|
|
@ -27,17 +27,17 @@
|
|||
:colorAnswers="item.colorAnswers"
|
||||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
||||
</div>
|
||||
<hr class="mt-7 mb-0" />
|
||||
<saveProgressModalQuestion
|
||||
modalWidgetName="SaveProgressModalWidget"
|
||||
pageName="vehicle-parts"
|
||||
v-if="showSaveProgressModal" />
|
||||
<navbar
|
||||
cmsWidgetName="FunnelFooterWidget"
|
||||
ref="navbar"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
@back-clicked="navigateBack"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
|
||||
<saveProgressModalQuestion
|
||||
modalWidgetName="SaveProgressModalWidget"
|
||||
pageName="vehicle-parts"
|
||||
v-if="showSaveProgressModal" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -242,10 +242,17 @@ export default {
|
|||
label {
|
||||
&.list-card {
|
||||
height: auto;
|
||||
border-radius: 50rem;
|
||||
input[type="radio"]:checked + .list-card-content {
|
||||
border-radius: 50rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
.two-list-card-width {
|
||||
width: 100%;
|
||||
}
|
||||
.save-progress-modal-question {
|
||||
margin: 1rem 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }">
|
||||
<funnelHeader cmsWidgetName="FunnelHeaderWidget" ref="funnelHeader" />
|
||||
<div class="container">
|
||||
<div class="container vehicle">
|
||||
<div class="row">
|
||||
<div class="col-12 col-md-10 col-lg-8 col-xl-7">
|
||||
<funnelSubHeader cmsWidgetName="FunnelSubHeaderWidget" class="siteSubHeader" />
|
||||
|
|
@ -631,8 +631,7 @@ export default {
|
|||
margin-bottom: 0;
|
||||
}
|
||||
.siteSubHeader {
|
||||
margin-top: 1.5rem;
|
||||
margin-bottom: 0;
|
||||
margin: 0;
|
||||
}
|
||||
.separator-line {
|
||||
grid-area: 2/1/2/8;
|
||||
|
|
|
|||
|
|
@ -80,6 +80,10 @@ export default {
|
|||
opacity: 1;
|
||||
visibility: visible;
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-family: UrbanistSemibold, Arial, Helvetica, sans-serif;
|
||||
}
|
||||
}
|
||||
.vin-info {
|
||||
max-height: 0;
|
||||
|
|
|
|||
|
|
@ -133,15 +133,6 @@ export default {
|
|||
const currentPageName = getPageNameFromRouter();
|
||||
const universes = store.getters.applicationUser.experiments;
|
||||
|
||||
let hasDynamoLogging = experimentMixin.methods.hasSettingEqualTo(
|
||||
experimentSettings.DYNAMO_LOGGING,
|
||||
"true",
|
||||
universes
|
||||
);
|
||||
if (!hasDynamoLogging) {
|
||||
return;
|
||||
}
|
||||
|
||||
const variationNames = universes
|
||||
.filter((item) => item.universeName === experimentUniverses.CONCEPT_FUNNEL)
|
||||
.map((item) => item.variationName)
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
position: relative;
|
||||
z-index: 5;
|
||||
@include box-shadow-hover($blue-300);
|
||||
border-radius: 0.5rem;
|
||||
border-radius: $border-radius-pill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ export default {
|
|||
|
||||
<style lang="scss">
|
||||
.list-button-horizontal {
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
position: absolute;
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ export default {
|
|||
width: 100%;
|
||||
outline: none;
|
||||
border-radius: 50rem;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
span {
|
||||
&.small {
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ export default {
|
|||
}
|
||||
.list-card {
|
||||
border: 1px solid $gray-500;
|
||||
box-shadow: 0px 1px 4px 0px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 5px 0 rgba(0, 0, 0, 0.2);
|
||||
|
||||
&.has-error {
|
||||
input[type="checkbox"],
|
||||
|
|
|
|||
Loading…
Reference in a new issue