409 lines
14 KiB
Vue
409 lines
14 KiB
Vue
<!-- Documented in confluence https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Component -->
|
|
<template>
|
|
<div
|
|
:class="
|
|
isOverflowScrollable
|
|
? 'button-question button-question-overflow'
|
|
: 'button-question'
|
|
">
|
|
<div
|
|
v-if="questionText && answers && answers.length > 0"
|
|
class="question-text d-flex">
|
|
<span class="fw-bold w-100">{{ questionText }}</span>
|
|
</div>
|
|
|
|
<div class="w-100 d-flex justify-content-center">
|
|
<fieldset
|
|
class="w-100"
|
|
:aria-required="isRequired"
|
|
:class="getFieldSetClasses"
|
|
:role="isMultiSelect ? 'group' : 'radiogroup'"
|
|
:aria-labelledby="formatString(groupName)"
|
|
@focusin="handleFocus"
|
|
@focusout="handleBlur">
|
|
<legend
|
|
class="sr-only"
|
|
:data-focus-target="formatString(groupName)"
|
|
tabindex="-1"
|
|
:id="formatString(groupName)">
|
|
{{ questionText }}
|
|
{{
|
|
isMultiSelect && answers && answers.length > 1
|
|
? "Select one or more options below."
|
|
: "Select an option below."
|
|
}}
|
|
</legend>
|
|
<div :class="getComponentLoopWrapperClasses">
|
|
<div
|
|
:class="getComponentWrapperClasses"
|
|
v-for="answer in buttonsInfo"
|
|
:key="answer.value ? answer.value : answer">
|
|
<component
|
|
:is="buttonType"
|
|
:buttonLabel="answer.buttonLabel"
|
|
:buttonLabelSubCopy="answer.buttonLabelSubCopy"
|
|
:buttonImage="answer.buttonImage"
|
|
:buttonImageId="answer.buttonImageId"
|
|
:groupName="answer.groupName"
|
|
:isMultiSelect="isMultiSelect"
|
|
:value="answer.value"
|
|
:modelValue="modelValue"
|
|
:selectingInitiatesLoad="selectingInitiatesLoad"
|
|
:isWide="isWide"
|
|
:validationRules="validationRules"
|
|
:textPosition="textPosition"
|
|
:selectOnKeypress="selectOnKeypress"
|
|
:lastValuePushedToGa="lastValuePushedToGa"
|
|
:setLastValuePushedToGa="setLastValuePushedToGa"
|
|
@inputButtonClicked="handleAnswerChange" />
|
|
<!-- For nested questions -->
|
|
<transition name="fade" mode="out-in">
|
|
<div
|
|
v-if="
|
|
typeof selectedValues == 'string' &&
|
|
selectedValues == answer.value
|
|
">
|
|
<slot></slot>
|
|
</div>
|
|
</transition>
|
|
</div>
|
|
</div>
|
|
</fieldset>
|
|
</div>
|
|
<div class="row form-test-error mt-1">
|
|
<error-message
|
|
:name="formatString(groupName)"
|
|
v-if="!suppressError"></error-message>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import listButton from "@/ux-components/list-button/list-button";
|
|
import listButtonHorizontal from "@/ux-components/list-button-horizontal/list-button-horizontal";
|
|
import listCard from "@/ux-components/list-card/list-card";
|
|
import radio from "@/ux-components/radio/radio";
|
|
import { ErrorMessage } from "vee-validate";
|
|
import { queryStrings } from "@/constants/query-strings";
|
|
import eventBus from "../../helpers/event-bus/event-bus";
|
|
|
|
export default {
|
|
name: "buttonQuestion",
|
|
props: {
|
|
buttonType: {
|
|
type: String,
|
|
default: "listButton",
|
|
},
|
|
isMultiSelect: Boolean,
|
|
groupName: String,
|
|
questionText: String,
|
|
answers: Array,
|
|
textPosition: {
|
|
type: String,
|
|
default: "text-center",
|
|
},
|
|
selectingInitiatesLoad: Boolean,
|
|
loaderColor: {
|
|
type: String,
|
|
default: "blue",
|
|
},
|
|
loaderPosition: {
|
|
type: String,
|
|
default: "right",
|
|
},
|
|
isRequired: Boolean,
|
|
isOverflowScrollable: Boolean,
|
|
isWide: Boolean,
|
|
isCashOrInsurance: Boolean,
|
|
modelValue: [Array, Number, String],
|
|
value: [Number, String],
|
|
validationRules: String,
|
|
suppressError: Boolean,
|
|
useTextForValue: Boolean,
|
|
valueToLogType: String,
|
|
selectOnKeypress: {
|
|
type: Boolean,
|
|
default: true,
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
selectedValues: "",
|
|
// lastFocusedInputGroup: "",
|
|
lastValuePushedToGa: null,
|
|
// mostRecentlySelectedValue: null,
|
|
};
|
|
},
|
|
computed: {
|
|
getFieldSetClasses() {
|
|
if (this.isOverflowScrollable) {
|
|
return "container-fluid overflow-scroll position-absolute px-5 pt-1 py-0";
|
|
} else if (this.buttonType == "listCard") {
|
|
return "w-100";
|
|
} else {
|
|
return "";
|
|
}
|
|
},
|
|
getComponentLoopWrapperClasses() {
|
|
let classes;
|
|
switch (this.buttonType) {
|
|
case "listButton":
|
|
classes = "w-100";
|
|
break;
|
|
case "listButtonHorizontal":
|
|
classes = "d-flex flex-row p-0";
|
|
break;
|
|
case "listCard":
|
|
classes = "row g-2 justify-content-center";
|
|
if (this.isWide) {
|
|
classes += " flex-column";
|
|
}
|
|
break;
|
|
case "radio":
|
|
classes = "ui-radio d-flex";
|
|
break;
|
|
}
|
|
return classes;
|
|
},
|
|
getComponentWrapperClasses() {
|
|
let classes = "";
|
|
|
|
classes += this.isWide ? "col-12" : "col";
|
|
|
|
if (this.buttonType == "radio") {
|
|
classes += " radio-button-container";
|
|
}
|
|
|
|
return classes;
|
|
},
|
|
getColLength() {
|
|
if (this.isWide) {
|
|
return "12";
|
|
} else {
|
|
return "";
|
|
}
|
|
},
|
|
buttonsInfo() {
|
|
// TODO KO temporary. It should always just be an array
|
|
return (Array.isArray(this.answers) ? this.answers : [])?.map(
|
|
(answer) => ({
|
|
buttonLabel: answer.buttonLabel ?? answer.Text ?? answer,
|
|
altText:
|
|
answer.altText ?? (answer.Name ? answer.Name : answer),
|
|
buttonLabelSubCopy:
|
|
answer.buttonLabelSubCopy ?? answer.SubText,
|
|
buttonImage: answer.buttonImage ?? answer.AnswerImageUrl,
|
|
buttonImageId: answer.buttonImageId ?? answer.ImageId,
|
|
groupName: this.formatString(this.groupName),
|
|
value:
|
|
answer.value ??
|
|
(this.useTextForValue
|
|
? answer.Text
|
|
: answer.Name ?? answer),
|
|
})
|
|
);
|
|
},
|
|
// isValueSelectedOnClick() {
|
|
// return this.isMultiSelect || this.selectingInitiatesLoad;
|
|
// },
|
|
},
|
|
methods: {
|
|
formatString(str) {
|
|
return str?.replace(" ", "-");
|
|
},
|
|
getValue(answer) {
|
|
if (this.useTextForValue) {
|
|
return answer.Text;
|
|
}
|
|
return answer.Name ? answer.Name : answer;
|
|
},
|
|
getAnswerString(answer, prop = "Name") {
|
|
switch (typeof answer) {
|
|
case "string":
|
|
case "number":
|
|
case "boolean":
|
|
return this.formatString(answer.toString());
|
|
default:
|
|
return answer[prop]
|
|
? this.formatString(answer[prop])
|
|
: this.formatString(answer.toString());
|
|
}
|
|
},
|
|
handleAnswerChange(selectedAnswers) {
|
|
this.selectedValues = selectedAnswers;
|
|
// if (lastValuePushedToGa) {
|
|
// this.lastValuePushedToGa = lastValuePushedToGa;
|
|
// // console.log("BQ lastValuePushedToGa: ", lastValuePushedToGa);
|
|
// }
|
|
|
|
// if (this.isValueSelectedOnClick) {
|
|
// this.pushClickEventToGA();
|
|
// }
|
|
|
|
this.$emit("buttonQuestionChange", selectedAnswers);
|
|
this.$emit("update:modelValue", selectedAnswers);
|
|
},
|
|
/////////////////////////////
|
|
setLastValuePushedToGa(lastValuePushedToGa) {
|
|
this.lastValuePushedToGa = lastValuePushedToGa;
|
|
},
|
|
// onFocusCallbackForRoot() {
|
|
// console.log("onFocusCallbackForRoot: ", {
|
|
// isValueSelectedOnClick: this.isValueSelectedOnClick,
|
|
// isChecked: this.isChecked,
|
|
// value: this.value,
|
|
// lastValuePushedToGa: this.lastValuePushedToGa,
|
|
// });
|
|
// if (
|
|
// !this.isValueSelectedOnClick &&
|
|
// // this.isChecked &&
|
|
// this.lastValuePushedToGa != this.mostRecentlySelectedValue
|
|
// ) {
|
|
// console.log("PUSH FROM ROOT CALLBACK");
|
|
// this.pushClickEventToGA();
|
|
// }
|
|
// },
|
|
// handleFocus(e) {
|
|
// // console.log("FOCUS :", {
|
|
// // groupName: this.groupName,
|
|
// // value: this.value,
|
|
// // });
|
|
// this.$root.handleInputFocus({
|
|
// groupName: this.groupName,
|
|
// });
|
|
// },
|
|
// handleBlur(e) {
|
|
// // console.log("BLUR :", {
|
|
// // groupName: this.groupName,
|
|
// // value: this.value
|
|
// // })
|
|
// this.$root.handleInputBlur({
|
|
// groupName: this.groupName,
|
|
// onFocusCallback: this.onFocusCallbackForRoot,
|
|
// });
|
|
// },
|
|
// pushClickEventToGA() {
|
|
// // const lastFocusedInputGroup =
|
|
// // this.$store.getters.gaClickInformation.lastFocusedInputGroup;
|
|
// // this.dispatchStoreAction(
|
|
// // gaStoreActions.UPDATE_FIRED_GA_CLICK_EVENT_VALUES,
|
|
// // {
|
|
// // groupName: lastFocusedInputGroup,
|
|
// // value: value ?? this.value,
|
|
// // },
|
|
// // );
|
|
|
|
// this.lastValuePushedToGa = this.mostRecentlySelectedValue;
|
|
// console.log("BIB");
|
|
// this.pushEventToGA(
|
|
// this.$route.query[queryStrings.FMG_PAGE],
|
|
// this.GaActions.CLICKED,
|
|
// this.mostRecentlySelectedValue?.toString(),
|
|
// true,
|
|
// this.valueToLogType
|
|
// );
|
|
// },
|
|
//////////////////////////////////
|
|
// pushClickEventToGA() {
|
|
// // const valueToPushToGa =
|
|
// // value?.toString() ?? this.selectedValues?.toString();
|
|
|
|
// // console.log("pushing")
|
|
// const event = eventBus.readAndPopEventFromBus("GA", "click");
|
|
// const valueToPushToGa = event?.label;
|
|
// console.log({
|
|
// valueToPushToGa,
|
|
// lastPushedGaEventValue: this.lastPushedGaEventValue,
|
|
// });onFocusCallbackForRoot() {
|
|
// console.log("Diff: ", this.isValueSelectedOnClick)
|
|
// if (!this.isValueSelectedOnClick) {
|
|
// this.pushClickEventToGA();
|
|
// }
|
|
// },
|
|
// handleFocus(e) {
|
|
// this.$root.handleInputFocus({
|
|
// groupName: this.groupName,
|
|
// });
|
|
// },
|
|
// handleBlur(e) {
|
|
// this.$root.handleInputBlur({
|
|
// groupName: this.groupName,
|
|
// onFocusCallback: this.onFocusCallbackForRoot,
|
|
// });
|
|
// },
|
|
// if (
|
|
// (event &&
|
|
// valueToPushToGa !== this.lastPushedGaEventValue) ||
|
|
// this.isValueSelectedOnClick
|
|
// ) {
|
|
// this.lastPushedGaEventValue = valueToPushToGa;
|
|
// this.pushEventToGA(
|
|
// event.category,
|
|
// event.action,
|
|
// valueToPushToGa,
|
|
// event.pushToLogType,
|
|
// event.valueToLogType
|
|
// );
|
|
// }
|
|
// },
|
|
//
|
|
},
|
|
components: {
|
|
listButton,
|
|
listButtonHorizontal,
|
|
listCard,
|
|
ErrorMessage,
|
|
radio,
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.button-question-overflow {
|
|
height: calc(100vh - 274px);
|
|
|
|
.overflow-scroll {
|
|
// Height will be determined by overall height of content above list
|
|
height: calc(100% - 314px);
|
|
overflow-x: hidden !important;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
}
|
|
.button-question {
|
|
color: $black;
|
|
|
|
.radio-button-container {
|
|
&:not(:last-child) {
|
|
padding-bottom: map-get($spacers, 2);
|
|
}
|
|
}
|
|
}
|
|
.question-text {
|
|
margin-top: 1.5rem;
|
|
margin-bottom: 1rem;
|
|
font-size: 1rem;
|
|
line-height: 1.625rem;
|
|
|
|
& > span {
|
|
text-align: center;
|
|
}
|
|
}
|
|
|
|
.vehicle-parts {
|
|
.question-text {
|
|
span {
|
|
font-size: 0.875rem;
|
|
text-align: left;
|
|
margin: 0 0 0.5rem 0;
|
|
}
|
|
}
|
|
.question-text {
|
|
margin: 0;
|
|
}
|
|
fieldset {
|
|
.ui-radio {
|
|
margin: 0;
|
|
}
|
|
}
|
|
}
|
|
</style>
|