DigitalConsumer.FixMyGlass/src/common-components/button-question/button-question.vue
2022-10-07 15:29:32 -04:00

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>