This commit is contained in:
Leah Schumann 2023-04-11 16:27:39 -04:00
parent c30f773d50
commit 3d2179d884
8 changed files with 180 additions and 24 deletions

View file

@ -86,6 +86,10 @@ const endpoints = {
url: "/parts/api/v1/parts/supporting-items",
method: "POST",
},
GetProviderLocations: {
url: "/location/api/v1/location/providers",
method: "GET",
},
GetCapabilityQuestions: {
url: "/parts/api/v1/parts/capability-questions",
method: "GET",

View file

@ -30,6 +30,7 @@ const storeActions = {
GET_MOLDING_QUESTIONS: "getMoldingQuestions",
GET_MOBILE_FEE_PART: "getMobileFeePart",
GET_SERVICEABILITY_DETAILS: "getServiceabilityDetails",
GET_PROVIDER_LOCATIONS: "getProviderLocations",
SAVE_SESSION: "saveSession",
LOAD_SESSION: "loadSession",
UPDATE_STORE_WITH_SAVE_SESSION_RESPONSE: "updateStoreWithSaveSessionResponse",

View file

@ -64,6 +64,11 @@
ref="mobileLocationQuestions"
linkWidgetName="MobileLocationLinkWidget"
modalWidgetName="MobileLocationModalWidget" />
<shopQuestion
ref="shopQuestion"
:isDropoff="isDropoff"
:serviceZipCode="zipCode"
cmsWidgetName="ShopQuestionWidget" />
<contentGroupModal ref="RecalModal" cmsWidgetName="RecalModal" />
<funnel-footer
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 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 shopQuestion from "@/layouts/service-location/shop-question/shop-question";
import funnelHeader from "@/fmg-components/funnel-header/funnel-header";
import funnelFooter from "@/fmg-components/funnel-footer/funnel-footer";
import funnelSubHeader from "@/fmg-components/funnel-sub-header/funnel-sub-header";
@ -149,6 +156,8 @@ export default {
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
const shopQuestionInitialDataPromise = shopQuestion.methods.loadInitialData();
// Settle promises and get results
const promiseResultMap = [
{
@ -167,6 +176,10 @@ export default {
resultKey: "zipCodeData",
promise: getZipCodeData,
},
{
resultKey: "shopQuestionInitialData",
promise: shopQuestionInitialDataPromise,
},
];
const resultMap = await settleAllPromises(promiseResultMap);
@ -179,6 +192,7 @@ export default {
resultMap.serviceabilityDetails,
resultMap.mobileFeePart
);
vm.$refs.shopQuestion.initializeComponent(resultMap.shopQuestionInitialData);
});
},
computed: {
@ -244,16 +258,15 @@ export default {
return this.isGlassServiceableInshop;
}
},
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
requiresInshopRecalibration() {
return (
this.isServiceableInshop &&
this.isGlassServiceableMobile &&
this.isRecalibrationServiceableMobile === false
isDualOrStaticRecalibration() {
const supportingItems = store.getters.lineItems.supportingItems;
return supportingItems.some(
(item) => item.partNumber === "RECAL STATIC" || item.partNumber === "RECAL DUAL"
);
},
displayRecalibrationWarning() {
return this.requiresInshopRecalibration;
return this.isDualOrStaticRecalibration;
},
displayServiceableInshopOnly() {
return (
@ -271,6 +284,9 @@ export default {
displayNoShopsAlert() {
return !this.isServiceableInshop && !this.isServiceableMobile;
},
isDropoff() {
return this.selectedAppointmentType === "Dropoff";
},
},
methods: {
arePagePrerequisitesValid() {
@ -352,6 +368,7 @@ export default {
Form,
loadingModal,
contentGroupModal,
shopQuestion,
},
};
</script>

View file

@ -0,0 +1 @@
test.todo("some test to be written in the future");

View file

@ -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>

View file

@ -1 +1 @@
test.todo("some test to be written in the future");
test.todo("some test to be written in the future");

View file

@ -9,6 +9,8 @@
alertClass="alert-info"
v-bind:isDismissible="false" />
<buttonQuestion
buttonTypeString="shopListButton"
:buttonTypeObject="shopListButton"
class="radioQuestion"
isOverflowScrollable
:questionText="questionText"
@ -24,6 +26,7 @@
<script>
import alert from "@/ux-components/alert/alert";
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 store from "@/store";
@ -42,6 +45,7 @@ export default {
data() {
return {
shops: [],
shopListButton: shopListButton,
};
},
props: {
@ -68,12 +72,14 @@ export default {
},
},
answers() {
// Map API result data, to address-vehicles data structure
const mappedData = this.shops.map((s) => {
// Map API result data
const mappedData = this.shops.map((shop) => {
return {
Name: s.providerNumber,
Text: `${s.city}<span class='distance'>${s.distance} mi</span>`,
SubText: `${s.streetAddress}, ${s.city}, ${s.state} ${s.zipCode}`,
Name: shop.providerNumber,
buttonLabel: shop.city,
buttonLabelSubCopy: `${shop.distance} mi`,
buttonBodyCopy: `${shop.streetAddress}, ${shop.city}, ${shop.state} ${shop.zipCode}`,
buttonAuxillaryCopy: `foo`
};
});
@ -123,21 +129,24 @@ export default {
font-weight: 500;
line-height: 1.5rem;
align-items: center;
margin-bottom: 0.25rem !important;
.distance {
margin-bottom: 0.25rem !important;
.button-label-sub-copy {
margin-bottom: 0rem !important;
color: #727676;
margin-left: 0.25rem;
padding-left: 0.25rem;
font-weight: 400;
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-right: 0.5rem !important;
}
</style>

View file

@ -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) {
const glassPartsArray = context.getters.lineItems.glassParts ?? [];
const carId = context.getters.vehicle.carId;