CSR-762 Fix for YMMS list-button keypresses

This commit is contained in:
Katie 2022-09-19 09:54:31 -04:00
parent 854300d677
commit 24ddb9f8a5
16 changed files with 216 additions and 184 deletions

View file

@ -53,7 +53,9 @@
:modelValue="modelValue"
selectingInitiatesLoad
:isWide="isWide"
@change="(e) => handleAnswerChange(e)"
:validationRules="validationRules"
:textPosition="textPosition"
@change="handleAnswerChange"
/>
<!-- <component
@ -269,7 +271,6 @@ export default {
listCard,
ErrorMessage,
radio,
// testButton,
},
};
</script>

View file

@ -1,5 +1,9 @@
<template>
<label :class="[ buttonWrapperClasses, { 'has-error': errors.length > 0 || hasError }]" :for="buttonId">
<label
:class="[buttonWrapperClasses, { 'has-error': errors.length > 0 }]"
:for="buttonId"
@mouseup.left="handleClick"
>
<!-- classes: {{classes}}<br/>
value: {{value}} <br/>
modelValue: {{modelValue}} <br/>
@ -12,7 +16,9 @@
:aria-required="isRequired"
:value="value"
:checked="isChecked"
@change="handleSelectionChange"
@keypress="handleSelectionChange"
@keypress.enter="handleClick"
@keypress.space="handleClick"
/>
<slot></slot>
@ -25,7 +31,7 @@ import { useField } from "vee-validate";
import { toRef } from "vue";
export default {
name: "button-wrapper",
name: "input-button-wrapper",
emits: ["change"],
model: {
prop: "modelValue",
@ -60,11 +66,19 @@ export default {
type: String,
required: true,
},
validationRules: String,
validationRules: {
type: String,
default: "",
},
buttonWrapperClasses: [String, Array, Object],
inputClasses: [String, Array, Object],
valueToLogType: String,
},
data() {
return {
valueToEmit: null,
};
},
methods: {
handleSelectionChange(event) {
// console.log(event);
@ -72,7 +86,7 @@ export default {
// console.log(this.modelValue);
let isChecked = event.target.checked;
// console.log("BM value: ", this.value);
let valueToEmit;
// let valueToEmit;
if (this.isMultiSelect && this.modelValue instanceof Array) {
let newValue = [...this.modelValue];
if (isChecked && !this.modelValue.includes(this.value)) {
@ -81,16 +95,25 @@ export default {
newValue.splice(newValue.indexOf(this.value), 1);
}
valueToEmit = newValue;
this.valueToEmit = newValue;
} else {
valueToEmit = this.value;
this.valueToEmit = this.value;
}
// console.log("ButtonWrapper is emitting: ", valueToEmit);
this.$emit("change", valueToEmit);
console.log("Not emitting");
this.handleChange(this.valueToEmit);
this.pushClickEventToGA();
},
handleClick(e) {
console.log("emitting");
console.log(e);
this.handleSelectionChange(e);
console.log(this.valueToEmit)
this.$emit("change", this.valueToEmit);
},
pushClickEventToGA() {
this.pushEventToGA(
this.$route.query[queryStrings.FMG_PAGE],
@ -119,8 +142,8 @@ export default {
const inputType = props.isMultiSelect ? "checkbox" : "radio";
const fieldOptions = {
// type: inputType,
// checkedValue: props.value,
type: inputType,
checkedValue: props.value,
// potentialInitialValue: props.selectedValues,
};
@ -134,6 +157,14 @@ export default {
// fieldOptions["initialValue"] = fieldOptions.potentialInitialValue;
// }
// const { handleChange, errors, value } = useField(
// toRef(props, "groupName"),
// toRef(props, "validationRules"),
// fieldOptions
// );
console.log(props.validationRules);
const { handleChange, errors, value } = useField(
toRef(props, "groupName"),
toRef(props, "validationRules"),
@ -152,7 +183,8 @@ export default {
};
</script>
<style lang="scss" scoped>
<!-- TODO KO Scope this? -->
<style lang="scss">
input {
opacity: 0;
height: 0.1px; // NOTE: cannot be zero or Safari can't put focus on it

View file

@ -43,12 +43,12 @@ export default ({
initializeComponent(replaceOptions){
this.replaceOptions = replaceOptions;
},
updateSelectedValues() {
// UPDATE SELECTEDVALUES IF ONLY ONE ANSWER
if(Array.isArray(this.answersToDisplay) && this.answersToDisplay.length === 1) {
this.selectedValues = [this.answersToDisplay[0].Name];
}
},
// updateSelectedValues() {
// // UPDATE SELECTEDVALUES IF ONLY ONE ANSWER
// if(Array.isArray(this.answersToDisplay) && this.answersToDisplay.length === 1) {
// this.selectedValues = [this.answersToDisplay[0].Name];
// }
// },
},
computed: {
questionText(){
@ -57,14 +57,14 @@ export default ({
answersFromCms(){
return this.getCmsContent(this.cmsWidgetName, 'Answers');
},
selectedValues: {
get: function() {
return this.modelValue;
},
set: function(newValue) {
this.$emit("update:modelValue", newValue);
}
},
// selectedValues: {
// get: function() {
// return this.modelValue;
// },
// set: function(newValue) {
// this.$emit("update:modelValue", newValue);
// }
// },
answersToDisplay(){
const filteredAnswers = Array.isArray(this.answersFromCms)
? this.answersFromCms.filter(ans =>

View file

@ -1,6 +1,6 @@
<template>
<Form
@submit="onSubmit"
@submit.prevent="onSubmit"
@invalid-submit="onInvalidSubmit"
ref="theForm"
v-slot="{ meta }"

View file

@ -7,7 +7,7 @@
:answers="makes"
groupName="ChooseVehicleMake"
textPosition="text-start"
v-model="selectedMake"
v-model="selectedValue"
isRequired
/>
</template>
@ -18,17 +18,17 @@ import buttonQuestion from "@/common-components/button-question/button-question"
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
import buttonQuestionWrapperMixin from "../../../mixins/button-question-wrapper-mixin";
export default {
name: "make-question",
mixins: [buttonQuestionWrapperMixin],
data() {
return {
makes: [],
selectedMake: null
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
computed: {
@ -50,10 +50,5 @@ export default {
this.makes = initialData;
},
},
watch: {
selectedMake(selectedMake) {
this.$emit("update:modelValue", selectedMake)
}
}
};
</script>

View file

@ -7,7 +7,7 @@
:answers="models"
groupName="ChooseVehicleModel"
textPosition="text-start"
v-model="selectedModel"
v-model="selectedValue"
isRequired
/>
</template>
@ -18,17 +18,17 @@ import buttonQuestion from "@/common-components/button-question/button-question"
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
import buttonQuestionWrapperMixin from "@/mixins/button-question-wrapper-mixin";
export default {
name: "model-question",
mixins: [buttonQuestionWrapperMixin],
data() {
return {
models: [],
selectedModel: null
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
computed: {
@ -50,10 +50,5 @@ export default {
this.models = initialData;
},
},
watch: {
selectedModel(selectedModel) {
this.$emit("update:modelValue", selectedModel);
}
}
};
</script>

View file

@ -7,7 +7,7 @@
:answers="styles"
groupName="ChooseVehicleStyle"
textPosition="text-start"
v-model="selectedStyle"
v-model="selectedValue"
isRequired
/>
</template>
@ -18,17 +18,17 @@ import buttonQuestion from "@/common-components/button-question/button-question"
import store from "@/store";
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
import buttonQuestionWrapperMixin from "@/mixins/button-question-wrapper-mixin";
export default {
name: "style-question",
mixins: [buttonQuestionWrapperMixin],
data() {
return {
styles: [],
selectedStyle: null
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
computed: {
@ -54,10 +54,5 @@ export default {
this.styles = initialData;
},
},
watch: {
selectedStyle(selectedStyle) {
this.$emit("update:modelValue", selectedStyle);
}
}
};
</script>

View file

@ -88,6 +88,7 @@ export default {
watch: {
selectedYear(year) {
console.log("selectedYear: ", year)
const parsedYear = parseInt(year);
this.dispatchStoreAction(storeActions.SAVE_VEHICLE_YEAR, parsedYear);
this.$router.navigateWithSaving(

View file

@ -8,7 +8,7 @@
:answers="years"
groupName="ChooseVehicleYear"
textPosition="text-start"
v-model="selectedYear"
v-model="selectedValue"
isRequired
/>
</div>
@ -19,20 +19,21 @@ import buttonQuestion from "@/common-components/button-question/button-question"
// Supporting files
import { storeActions } from "@/constants/store-actions.js";
import baseMixin from "@/mixins/base-mixin.js";
import buttonQuestionWrapperMixin from "@/mixins/button-question-wrapper-mixin";
export default {
name: "year-question",
mixins: [buttonQuestionWrapperMixin],
data() {
return {
years: [],
selectedYear: null,
};
},
props: {
modelValue: String,
cmsWidgetName: String,
},
components: {
buttonQuestion,
buttonQuestion
},
computed: {
questionText() {
@ -50,10 +51,5 @@ export default {
this.years = initialData;
},
},
watch: {
selectedYear(selectedYear) {
this.$emit("update:modelValue", selectedYear)
}
}
};
</script>

View file

@ -32,7 +32,7 @@ export default {
savePageDataToStore(page, data) {
store.commit(storeMutations.UPDATE_PAGE_DATA, { page: page, data: data });
},
onSubmit() { }, // DO NOT REMOVE; needed to prevent default form submit behavior
// onSubmit() { }, // DO NOT REMOVE; needed to prevent default form submit behavior
onInvalidSubmit({ values, errors, results }) {
// identify the first error field and put focus on it
// get error names array

View file

@ -1,5 +0,0 @@
import { queryStrings } from "@/constants/query-strings";
export default {
};

View file

@ -0,0 +1,16 @@
export default {
props: {
modelValue: String,
},
data() {
return {
selectedValue: null,
};
},
watch: {
selectedValue(selectedValue) {
console.log("selectedValue: ", selectedValue)
this.$emit("update:modelValue", selectedValue);
},
},
};

View file

@ -3,7 +3,7 @@ html {
&.list-button,
&.list-card,
&.list-card.list-button {
border: none;
// border: none;
color: $red;
input[type=checkbox]:focus + label,
input[type=radio]:focus + label {

View file

@ -23,13 +23,13 @@
LB modelValue: {{ modelValue }}
LB groupName: {{ groupName }} -->
<!-- , {'has-error': errors.length > 0 || hasError} -->
<!-- <buttonWrapper
<!-- <inputButtonWrapper
v-bind="$props"
:classes="['list-group list-button rounded-3 d-flex flex-column w-100 mb-2', {'has-error': errors.length > 0 || hasError}]"
@change="(e) => $emit('change', e)"
> -->
<buttonWrapper
<inputButtonWrapper
:isMultiSelect="isMultiSelect"
:modelValue="modelValue"
:value="value"
@ -56,7 +56,7 @@
:class="[this.loaderColor, this.loaderPosition]"
/>
</div>
</buttonWrapper>
</inputButtonWrapper>
<!-- </label> -->
<!-- </div> -->
</template>
@ -65,13 +65,10 @@
// import { useField } from "vee-validate";
// import { toRef } from "vue";
import loader from "@/ux-components/loader/loader";
import { queryStrings } from "@/constants/query-strings";
import buttonMixin from "@/mixins/button-mixin";
import buttonWrapper from "@/common-components/button-wrapper/button-wrapper";
import inputButtonWrapper from "@/common-components/input-button-wrapper/input-button-wrapper";
export default {
name: "listButton",
mixins: [buttonMixin],
props: {
// groupName: String,
buttonLabel: [Number, String],
@ -120,10 +117,18 @@ export default {
this.isLoaderDisplayed = true;
},
handleAnswerChange(e) {
// TODO KO make it work on YMMS with keypresses
// There must be a way to tell the difference between keypress and
// submit via veevalidate. Check out the Form in vehicle-damage
if (this.selectingInitiatesLoad) {
this.displayLoader();
}
console.log("lbTest event: ", e);
// else {
// console.log("lbTest event: ", e);
// // this.$emit("change", e);
// }
console.log(e)
this.$emit("change", e);
},
// handleInputChange() {
@ -143,14 +148,14 @@ export default {
}
// TODO KO THIS IS IMPORTANT
// Move this to button-wrapper?
this.pushEventToGA(
this.$route.query[queryStrings.FMG_PAGE],
this.GaActions.CLICKED,
this.value.toString(),
true,
this.valueToLogType
);
// Move this to input-button-wrapper?
// this.pushEventToGA(
// this.$route.query[queryStrings.FMG_PAGE],
// this.GaActions.CLICKED,
// this.value.toString(),
// true,
// this.valueToLogType
// );
},
// handleCheckChange() {
// const emitEvent = {
@ -166,7 +171,7 @@ export default {
},
components: {
loader,
buttonWrapper,
inputButtonWrapper,
},
// setup(props) {
// const inputType = props.isMultiSelect ? "checkbox" : "radio";

View file

@ -1,13 +1,14 @@
<template>
<buttonWrapper
<inputButtonWrapper
:buttonWrapperClasses="[
'list-card w-100 rounded-3 d-flex align-items-center h-100',
{ 'horizontal': isWide, 'has-error': errors.length > 0 || hasError }
{ 'horizontal': isWide }
]"
:isMultiSelect="isMultiSelect"
:modelValue="modelValue"
:value="value"
:groupName="groupName"
:validationRules="validationRules"
@change="handleAnswerChange"
>
@ -65,19 +66,19 @@
</div>
<!-- </div>
</div> -->
</buttonWrapper>
</inputButtonWrapper>
</template>
<script>
import { useField } from "vee-validate";
import { toRef } from "vue";
import { queryStrings } from "@/constants/query-strings";
import buttonWrapper from "@/common-components/button-wrapper/button-wrapper";
import inputButtonWrapper from "@/common-components/input-button-wrapper/input-button-wrapper";
export default {
name: "listCard",
components: {
buttonWrapper
inputButtonWrapper
},
props: {
isMultiSelect: Boolean, //Defines use as checkbox
@ -97,29 +98,29 @@ export default {
},
// colLength: String,
validationRules: String,
selectedValues: [Array, String],
hasError: Boolean,
// selectedValues: [Array, String],
// hasError: Boolean,
valueToLogType: String,
},
data() {
return {
checkValue: null,
// checkValue: null,
};
},
mounted() {
if (Array.isArray(this.validateValue)) {
this.checkValue = this.isValueSelectedByArray(this.selectedValues);
const isSelectedByValidator = this.isValueSelectedByArray(
this.validateValue
);
// mounted() {
// if (Array.isArray(this.validateValue)) {
// this.checkValue = this.isValueSelectedByArray(this.selectedValues);
// const isSelectedByValidator = this.isValueSelectedByArray(
// this.validateValue
// );
if (this.checkValue != isSelectedByValidator) {
this.handleChange(this.value);
}
} else {
this.checkValue = this.selectedValues == this.value;
}
},
// if (this.checkValue != isSelectedByValidator) {
// this.handleChange(this.value);
// }
// } else {
// this.checkValue = this.selectedValues == this.value;
// }
// },
computed: {
getLabelClasses() {
if (this.isWide) {
@ -134,47 +135,47 @@ export default {
},
},
methods: {
isValueSelectedByArray(arr) {
return this.isMultiSelect ? arr.includes(this.value) : arr[0];
},
handleInputChange() {
if (!this.selectingInitiatesLoad) {
this.handleCheckChange();
}
},
handleKeyupArrow() {
if (this.isMultiSelect) {
return; // Prevent arrow keys from doing anything if element is a checkbox
}
// isValueSelectedByArray(arr) {
// return this.isMultiSelect ? arr.includes(this.value) : arr[0];
// },
// handleInputChange() {
// if (!this.selectingInitiatesLoad) {
// this.handleCheckChange();
// }
// },
// handleKeyupArrow() {
// if (this.isMultiSelect) {
// return; // Prevent arrow keys from doing anything if element is a checkbox
// }
if (!this.selectingInitiatesLoad) {
this.handleCheckChange();
}
},
triggerButton() {
if (this.selectingInitiatesLoad) {
this.displayLoader();
this.handleCheckChange();
}
// if (!this.selectingInitiatesLoad) {
// this.handleCheckChange();
// }
// },
// triggerButton() {
// if (this.selectingInitiatesLoad) {
// this.displayLoader();
// this.handleCheckChange();
// }
this.pushEventToGA(
this.$route.query[queryStrings.FMG_PAGE],
this.GaActions.CLICKED,
this.value.toString(),
true,
this.valueToLogType
);
},
handleCheckChange() {
const emitEvent = {
checkValue: this.checkValue, // only read on checkboxes, on handleCheckedChanged on button-question
value: this.value.toString(),
buttonId: this.buttonID && this.buttonID.toString(),
};
// this.pushEventToGA(
// this.$route.query[queryStrings.FMG_PAGE],
// this.GaActions.CLICKED,
// this.value.toString(),
// true,
// this.valueToLogType
// );
// },
// handleCheckChange() {
// const emitEvent = {
// checkValue: this.checkValue, // only read on checkboxes, on handleCheckedChanged on button-question
// value: this.value.toString(),
// buttonId: this.buttonID && this.buttonID.toString(),
// };
this.handleChange(this.value);
this.$emit("isCheckedChanged", emitEvent);
},
// this.handleChange(this.value);
// this.$emit("isCheckedChanged", emitEvent);
// },
handleAnswerChange(e) {
this.$emit("change", e);
},
@ -182,49 +183,49 @@ export default {
watch: {
// Changing this will impact pre-selection data loads on vehicle-parts.
// If changed, please regression test that vehicle-parts data still loads correctly with previous selections.
selectedValues(newVal) {
if (typeof newVal === "string") {
this.checkValue = newVal == this.value;
} else if (newVal !== undefined) {
this.checkValue = newVal.value;
}
},
// selectedValues(newVal) {
// if (typeof newVal === "string") {
// this.checkValue = newVal == this.value;
// } else if (newVal !== undefined) {
// this.checkValue = newVal.value;
// }
// },
},
setup(props) {
const inputType = props.isMultiSelect ? "checkbox" : "radio";
// setup(props) {
// const inputType = props.isMultiSelect ? "checkbox" : "radio";
const fieldOptions = {
type: inputType,
checkedValue: props.value, // EX: "Single" or "Passenger"
potentialInitialValue: props.selectedValues,
};
// const fieldOptions = {
// type: inputType,
// checkedValue: props.value, // EX: "Single" or "Passenger"
// potentialInitialValue: props.selectedValues,
// };
// Set initialValue for validation setup if pre-selected
// NOTE: props.selectedValues could be an array of strings, or an array of integers...
if (
props.selectedValues &&
(props.selectedValues.includes(props.value) ||
props.selectedValues.includes(parseInt(props.value)))
) {
fieldOptions["initialValue"] = fieldOptions.potentialInitialValue;
}
// // Set initialValue for validation setup if pre-selected
// // NOTE: props.selectedValues could be an array of strings, or an array of integers...
// if (
// props.selectedValues &&
// (props.selectedValues.includes(props.value) ||
// props.selectedValues.includes(parseInt(props.value)))
// ) {
// fieldOptions["initialValue"] = fieldOptions.potentialInitialValue;
// }
const { handleChange, errors, value } = useField(
toRef(props, "groupName"),
toRef(props, "validationRules"),
fieldOptions
);
// const { handleChange, errors, value } = useField(
// toRef(props, "groupName"),
// toRef(props, "validationRules"),
// fieldOptions
// );
// First land on the blank, unselected page, no handleChange
// Land on page with initial values, handleChange
const validateValue = value;
return {
handleChange,
errors,
validateValue,
fieldOptions, // only need to expose this for unit test purposes
};
},
// // First land on the blank, unselected page, no handleChange
// // Land on page with initial values, handleChange
// const validateValue = value;
// return {
// handleChange,
// errors,
// validateValue,
// fieldOptions, // only need to expose this for unit test purposes
// };
// },
};
</script>
@ -232,7 +233,7 @@ export default {
.list-card {
border: 1px solid $gray-500;
&.invalid {
&.has-error {
//Red border if invalid
border: 1px solid $red;
}

View file

@ -1,5 +1,5 @@
process.env.VUE_APP_CONSUMER_CF_DISTRO =
"https://consumerapidev.safelite.com";
"https://consumerapialbdev.safelite.com";
process.env.VUE_APP_HERITAGE_FUNNEL =
"http://localhost:38000/default.aspx";
process.env.VUE_APP_GOOGLE_PLACES_API_KEY =