WIP
This commit is contained in:
parent
c30f773d50
commit
3d2179d884
8 changed files with 180 additions and 24 deletions
|
|
@ -86,6 +86,10 @@ const endpoints = {
|
||||||
url: "/parts/api/v1/parts/supporting-items",
|
url: "/parts/api/v1/parts/supporting-items",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
GetProviderLocations: {
|
||||||
|
url: "/location/api/v1/location/providers",
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
GetCapabilityQuestions: {
|
GetCapabilityQuestions: {
|
||||||
url: "/parts/api/v1/parts/capability-questions",
|
url: "/parts/api/v1/parts/capability-questions",
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ const storeActions = {
|
||||||
GET_MOLDING_QUESTIONS: "getMoldingQuestions",
|
GET_MOLDING_QUESTIONS: "getMoldingQuestions",
|
||||||
GET_MOBILE_FEE_PART: "getMobileFeePart",
|
GET_MOBILE_FEE_PART: "getMobileFeePart",
|
||||||
GET_SERVICEABILITY_DETAILS: "getServiceabilityDetails",
|
GET_SERVICEABILITY_DETAILS: "getServiceabilityDetails",
|
||||||
|
GET_PROVIDER_LOCATIONS: "getProviderLocations",
|
||||||
SAVE_SESSION: "saveSession",
|
SAVE_SESSION: "saveSession",
|
||||||
LOAD_SESSION: "loadSession",
|
LOAD_SESSION: "loadSession",
|
||||||
UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse",
|
UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse",
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,11 @@
|
||||||
ref="mobileLocationQuestions"
|
ref="mobileLocationQuestions"
|
||||||
linkWidgetName="MobileLocationLinkWidget"
|
linkWidgetName="MobileLocationLinkWidget"
|
||||||
modalWidgetName="MobileLocationModalWidget" />
|
modalWidgetName="MobileLocationModalWidget" />
|
||||||
|
<shopQuestion
|
||||||
|
ref="shopQuestion"
|
||||||
|
:isDropoff="isDropoff"
|
||||||
|
:serviceZipCode="zipCode"
|
||||||
|
cmsWidgetName="ShopQuestionWidget" />
|
||||||
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
|
||||||
<funnel-footer
|
<funnel-footer
|
||||||
cmsWidgetName="FunnelFooterWidget"
|
cmsWidgetName="FunnelFooterWidget"
|
||||||
|
|
@ -81,6 +86,8 @@ import alert from "@/ux-components/alert/alert";
|
||||||
import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question";
|
import serviceZipModalQuestion from "@/layouts/service-location/service-zip-modal-question/service-zip-modal-question";
|
||||||
import mobileLocationModalQuestions from "@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions";
|
import mobileLocationModalQuestions from "@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions";
|
||||||
import appointmentTypeQuestion from "@/layouts/service-location/appointment-type-question/appointment-type-question";
|
import appointmentTypeQuestion from "@/layouts/service-location/appointment-type-question/appointment-type-question";
|
||||||
|
import shopQuestion from "@/layouts/service-location/shop-question/shop-question";
|
||||||
|
|
||||||
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
|
||||||
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
|
||||||
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
|
@ -149,6 +156,8 @@ export default {
|
||||||
|
|
||||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
||||||
|
|
||||||
|
const shopQuestionInitialDataPromise = shopQuestion.methods.loadInitialData();
|
||||||
|
|
||||||
// Settle promises and get results
|
// Settle promises and get results
|
||||||
const promiseResultMap = [
|
const promiseResultMap = [
|
||||||
{
|
{
|
||||||
|
|
@ -167,6 +176,10 @@ export default {
|
||||||
resultKey: "zipCodeData",
|
resultKey: "zipCodeData",
|
||||||
promise: getZipCodeData,
|
promise: getZipCodeData,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
resultKey: "shopQuestionInitialData",
|
||||||
|
promise: shopQuestionInitialDataPromise,
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const resultMap = await settleAllPromises(promiseResultMap);
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
@ -179,6 +192,7 @@ export default {
|
||||||
resultMap.serviceabilityDetails,
|
resultMap.serviceabilityDetails,
|
||||||
resultMap.mobileFeePart
|
resultMap.mobileFeePart
|
||||||
);
|
);
|
||||||
|
vm.$refs.shopQuestion.initializeComponent(resultMap.shopQuestionInitialData);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -244,16 +258,15 @@ export default {
|
||||||
return this.isGlassServiceableInshop;
|
return this.isGlassServiceableInshop;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
|
isDualOrStaticRecalibration() {
|
||||||
requiresInshopRecalibration() {
|
const supportingItems = store.getters.lineItems.supportingItems;
|
||||||
return (
|
|
||||||
this.isServiceableInshop &&
|
return supportingItems.some(
|
||||||
this.isGlassServiceableMobile &&
|
(item) => item.partNumber === "RECAL STATIC" || item.partNumber === "RECAL DUAL"
|
||||||
this.isRecalibrationServiceableMobile === false
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
displayRecalibrationWarning() {
|
displayRecalibrationWarning() {
|
||||||
return this.requiresInshopRecalibration;
|
return this.isDualOrStaticRecalibration;
|
||||||
},
|
},
|
||||||
displayServiceableInshopOnly() {
|
displayServiceableInshopOnly() {
|
||||||
return (
|
return (
|
||||||
|
|
@ -271,6 +284,9 @@ export default {
|
||||||
displayNoShopsAlert() {
|
displayNoShopsAlert() {
|
||||||
return !this.isServiceableInshop && !this.isServiceableMobile;
|
return !this.isServiceableInshop && !this.isServiceableMobile;
|
||||||
},
|
},
|
||||||
|
isDropoff() {
|
||||||
|
return this.selectedAppointmentType === "Dropoff";
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
arePagePrerequisitesValid() {
|
arePagePrerequisitesValid() {
|
||||||
|
|
@ -352,6 +368,7 @@ export default {
|
||||||
Form,
|
Form,
|
||||||
loadingModal,
|
loadingModal,
|
||||||
contentGroupModal,
|
contentGroupModal,
|
||||||
|
shopQuestion,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
test.todo("some test to be written in the future");
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
<template>
|
||||||
|
<baseInputButton
|
||||||
|
v-bind="$props"
|
||||||
|
buttonWrapperClasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2"
|
||||||
|
v-model="selectedValue">
|
||||||
|
<div
|
||||||
|
:aria-label="buttonLabel"
|
||||||
|
class="button-content list-button-content d-flex flex-column justify-content-center py-3 px-4">
|
||||||
|
<span class="m-0 button-label-copy" :class="textPosition">
|
||||||
|
{{ buttonLabel }}
|
||||||
|
<span class="m-0 button-label-sub-copy" :class="textPosition">{{ buttonLabelSubCopy }}</span>
|
||||||
|
<span class="m-0 button-auxillary-copy text-end">{{ buttonAuxillaryCopy }}</span>
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
v-if="buttonBodyCopy"
|
||||||
|
class="m-0 button-label-sub-copy small"
|
||||||
|
:class="textPosition"
|
||||||
|
v-html="buttonBodyCopy"></span>
|
||||||
|
<span v-if="screenReaderOnlyText" class="sr-only">
|
||||||
|
{{ screenReaderOnlyText }}
|
||||||
|
</span>
|
||||||
|
<loader
|
||||||
|
v-if="isLoaderDisplayed && selectingInitiatesLoad"
|
||||||
|
:class="[this.loaderColor, this.loaderPosition]" />
|
||||||
|
</div>
|
||||||
|
</baseInputButton>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import loader from "@/ux-components/loader/loader";
|
||||||
|
import baseInputButton from "@/digital-components/base-input-button/base-input-button";
|
||||||
|
import inputButtonWrapperMixin from "@/mixins/input-button-wrapper-mixin";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "shopListButton",
|
||||||
|
mixins: [inputButtonWrapperMixin],
|
||||||
|
props: {
|
||||||
|
loaderColor: String,
|
||||||
|
loaderPosition: {
|
||||||
|
type: String,
|
||||||
|
default: "right",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isLoaderDisplayed: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
displayLoader() {
|
||||||
|
this.isLoaderDisplayed = true;
|
||||||
|
},
|
||||||
|
preHandleAnswerChange() {
|
||||||
|
if (this.selectingInitiatesLoad) {
|
||||||
|
this.displayLoader();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
loader,
|
||||||
|
baseInputButton,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.loader {
|
||||||
|
position: absolute;
|
||||||
|
}
|
||||||
|
.list-button {
|
||||||
|
outline: none;
|
||||||
|
input[type="radio"],
|
||||||
|
input[type="checkbox"] {
|
||||||
|
position: static; //override bootstrap
|
||||||
|
|
||||||
|
&:focus-visible + .list-button-content {
|
||||||
|
box-shadow: 0 0 0 2.5px $blue;
|
||||||
|
}
|
||||||
|
&:focus + .list-button-content {
|
||||||
|
box-shadow: 0 0 0 2.5px $blue;
|
||||||
|
}
|
||||||
|
&:checked + .list-button-content {
|
||||||
|
color: $black;
|
||||||
|
font-weight: 500;
|
||||||
|
background: $blue-100;
|
||||||
|
box-shadow: 0 0 0 1px $blue;
|
||||||
|
}
|
||||||
|
&:checked:focus + .list-button-content {
|
||||||
|
box-shadow: 0 0 0 2.5px $blue;
|
||||||
|
}
|
||||||
|
&:checked + .list-button-content p,
|
||||||
|
&:checked + .list-button-content span {
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
&:checked + .list-button-content span:nth-child(2) {
|
||||||
|
font-weight: 400;
|
||||||
|
color: $gray-600;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.list-button-content {
|
||||||
|
color: $gray-600;
|
||||||
|
position: relative;
|
||||||
|
background: $white;
|
||||||
|
transition: all 150ms linear;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
border: 1px solid $gray-500;
|
||||||
|
width: 100%;
|
||||||
|
outline: none;
|
||||||
|
|
||||||
|
span {
|
||||||
|
&.small {
|
||||||
|
font-size: 0.75rem;
|
||||||
|
color: $gray-550;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
alertClass="alert-info"
|
alertClass="alert-info"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
<buttonQuestion
|
<buttonQuestion
|
||||||
|
buttonTypeString="shopListButton"
|
||||||
|
:buttonTypeObject="shopListButton"
|
||||||
class="radioQuestion"
|
class="radioQuestion"
|
||||||
isOverflowScrollable
|
isOverflowScrollable
|
||||||
:questionText="questionText"
|
:questionText="questionText"
|
||||||
|
|
@ -24,6 +26,7 @@
|
||||||
<script>
|
<script>
|
||||||
import alert from "@/ux-components/alert/alert";
|
import alert from "@/ux-components/alert/alert";
|
||||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
|
import shopListButton from "./shop-list-button/shop-list-button";
|
||||||
|
|
||||||
import { storeActions } from "@/constants/store-actions.js";
|
import { storeActions } from "@/constants/store-actions.js";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
|
|
@ -42,6 +45,7 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
shops: [],
|
shops: [],
|
||||||
|
shopListButton: shopListButton,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -68,12 +72,14 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
answers() {
|
answers() {
|
||||||
// Map API result data, to address-vehicles data structure
|
// Map API result data
|
||||||
const mappedData = this.shops.map((s) => {
|
const mappedData = this.shops.map((shop) => {
|
||||||
return {
|
return {
|
||||||
Name: s.providerNumber,
|
Name: shop.providerNumber,
|
||||||
Text: `${s.city}<span class='distance'>${s.distance} mi</span>`,
|
buttonLabel: shop.city,
|
||||||
SubText: `${s.streetAddress}, ${s.city}, ${s.state} ${s.zipCode}`,
|
buttonLabelSubCopy: `${shop.distance} mi`,
|
||||||
|
buttonBodyCopy: `${shop.streetAddress}, ${shop.city}, ${shop.state} ${shop.zipCode}`,
|
||||||
|
buttonAuxillaryCopy: `foo`
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -125,19 +131,22 @@ export default {
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin-bottom: 0.25rem !important;
|
margin-bottom: 0.25rem !important;
|
||||||
|
|
||||||
.distance {
|
.button-label-sub-copy {
|
||||||
|
margin-bottom: 0rem !important;
|
||||||
color: #727676;
|
color: #727676;
|
||||||
margin-left: 0.25rem;
|
padding-left: 0.25rem;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
line-height: 1.25rem;
|
line-height: 1.25rem;
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.button-auxillary-copy {
|
||||||
|
display: flex;
|
||||||
|
align-items: right;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-label-sub-copy {
|
|
||||||
font-weight: 400;
|
|
||||||
margin-bottom: 0rem !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -152,6 +161,4 @@ export default {
|
||||||
padding-left: 1.5rem !important;
|
padding-left: 1.5rem !important;
|
||||||
padding-right: 0.5rem !important;
|
padding-right: 0.5rem !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -937,6 +937,14 @@ export const actions = {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
getProviderLocations(context, { serviceZipCode }) {
|
||||||
|
return globalMethods.callMockHttpClient({
|
||||||
|
method: endpoints.GetProviderLocations.method,
|
||||||
|
//TODO: Remove Mocky Endpoints
|
||||||
|
endpoint: "https://run.mocky.io/v3/2a82baf7-c6e8-40ac-8e2e-9d91800c7f9b",
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
getSupportingItems(context) {
|
getSupportingItems(context) {
|
||||||
const glassPartsArray = context.getters.lineItems.glassParts ?? [];
|
const glassPartsArray = context.getters.lineItems.glassParts ?? [];
|
||||||
const carId = context.getters.vehicle.carId;
|
const carId = context.getters.vehicle.carId;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue