Merge branch 'develop' into feature/SSR-233
This commit is contained in:
commit
4341ed913b
13 changed files with 549 additions and 452 deletions
|
|
@ -1,76 +1,79 @@
|
||||||
<!-- Documented in confluence https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Component -->
|
<!-- Documented in confluence https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Component -->
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
:class="
|
:class="
|
||||||
isOverflowScrollable ? 'button-question button-question-overflow' : 'button-question'
|
isOverflowScrollable ? 'button-question button-question-overflow' : 'button-question'
|
||||||
">
|
">
|
||||||
<div v-if="questionText && answers && answers.length > 0" class="question-text d-flex">
|
<div v-if="questionText && answers && answers.length > 0" class="question-text d-flex">
|
||||||
<span class="fw-bold w-100">{{ questionText }}</span>
|
<span class="fw-bold w-100">{{ questionText }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-100 d-flex justify-content-center">
|
<div class="w-100 d-flex justify-content-center">
|
||||||
<fieldset
|
<fieldset
|
||||||
class="w-100"
|
class="w-100"
|
||||||
:aria-required="isRequired"
|
:aria-required="isRequired"
|
||||||
:class="getFieldSetClasses"
|
:class="getFieldSetClasses"
|
||||||
:role="isMultiSelect ? 'group' : 'radiogroup'"
|
:role="isMultiSelect ? 'group' : 'radiogroup'"
|
||||||
:aria-labelledby="formatString(groupName)">
|
:aria-labelledby="formatString(groupName)">
|
||||||
<legend
|
<legend
|
||||||
class="sr-only"
|
class="sr-only"
|
||||||
:data-focus-target="formatString(groupName)"
|
:data-focus-target="formatString(groupName)"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
:id="formatString(groupName)">
|
:id="formatString(groupName)">
|
||||||
{{ questionText }}
|
{{ questionText }}
|
||||||
{{
|
{{
|
||||||
isMultiSelect && answers && answers.length > 1
|
isMultiSelect && answers && answers.length > 1
|
||||||
? "Select one or more options below."
|
? "Select one or more options below."
|
||||||
: "Select an option below."
|
: "Select an option below."
|
||||||
}}
|
}}
|
||||||
</legend>
|
</legend>
|
||||||
<div :class="getComponentLoopWrapperClasses">
|
<div :class="getComponentLoopWrapperClasses">
|
||||||
<div
|
<div
|
||||||
:class="getComponentWrapperClasses"
|
:class="getComponentWrapperClasses"
|
||||||
v-for="answer in buttonsInfo"
|
v-for="answer in buttonsInfo"
|
||||||
:key="answer.value ? answer.value : answer">
|
:key="answer.value ? answer.value : answer">
|
||||||
<component
|
<component
|
||||||
:is="buttonTypeString"
|
:is="buttonTypeString"
|
||||||
:buttonLabel="answer.buttonLabel"
|
:buttonLabel="answer.buttonLabel"
|
||||||
:buttonLabelSubCopy="answer.buttonLabelSubCopy"
|
:buttonLabelSubCopy="answer.buttonLabelSubCopy"
|
||||||
:buttonBodyCopy="answer.buttonBodyCopy"
|
:buttonBodyCopy="answer.buttonBodyCopy"
|
||||||
:buttonAuxillaryCopy="answer.buttonAuxillaryCopy"
|
:buttonAuxillaryCopy="answer.buttonAuxillaryCopy"
|
||||||
:buttonFooterCopy="answer.buttonFooterCopy"
|
:buttonFooterCopy="answer.buttonFooterCopy"
|
||||||
:buttonImage="answer.buttonImage"
|
:buttonImage="answer.buttonImage"
|
||||||
:buttonImageId="answer.buttonImageId"
|
:buttonImageId="answer.buttonImageId"
|
||||||
:groupName="answer.groupName"
|
:groupName="answer.groupName"
|
||||||
:isMultiSelect="isMultiSelect"
|
:isMultiSelect="isMultiSelect"
|
||||||
:value="answer.value"
|
:value="answer.value"
|
||||||
:selectingInitiatesLoad="selectingInitiatesLoad"
|
:selectingInitiatesLoad="selectingInitiatesLoad"
|
||||||
:isWide="isWide"
|
:isWide="isWide"
|
||||||
:validationRules="validationRules"
|
:validationRules="validationRules"
|
||||||
:textPosition="textPosition"
|
:textPosition="textPosition"
|
||||||
:additionalButtonStyling="additionalButtonStyling"
|
:additionalButtonStyling="additionalButtonStyling"
|
||||||
:lastValuePushedToGa="lastValuePushedToGa"
|
:lastValuePushedToGa="lastValuePushedToGa"
|
||||||
:setLastValuePushedToGa="setLastValuePushedToGa"
|
:setLastValuePushedToGa="setLastValuePushedToGa"
|
||||||
:suppressError="suppressError"
|
:suppressError="suppressError"
|
||||||
v-model="selectedValues" />
|
v-model="selectedValues" />
|
||||||
<!-- For nested questions -->
|
<!-- For nested questions -->
|
||||||
<transition name="fade" mode="out-in">
|
<transition name="fade" mode="out-in">
|
||||||
<div
|
<div
|
||||||
v-if="
|
v-if="
|
||||||
typeof selectedValues == 'string' &&
|
typeof selectedValues == 'string' &&
|
||||||
selectedValues == answer.value
|
selectedValues == answer.value
|
||||||
">
|
">
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
</div>
|
</div>
|
||||||
<div class="row form-test-error mt-1">
|
<div class="row form-test-error mt-1">
|
||||||
<error-message :name="formatString(groupName)" v-if="!suppressError"></error-message>
|
<error-message
|
||||||
</div>
|
class="small"
|
||||||
</div>
|
:name="formatString(groupName)"
|
||||||
|
v-if="!suppressError"></error-message>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -81,195 +84,193 @@ import radio from "@/ux-components/radio/radio";
|
||||||
import { ErrorMessage } from "vee-validate";
|
import { ErrorMessage } from "vee-validate";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "buttonQuestion",
|
name: "buttonQuestion",
|
||||||
props: {
|
props: {
|
||||||
buttonTypeString: {
|
buttonTypeString: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "listButton",
|
default: "listButton",
|
||||||
},
|
},
|
||||||
buttonTypeObject: {
|
buttonTypeObject: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: null,
|
default: null,
|
||||||
},
|
},
|
||||||
isMultiSelect: Boolean,
|
isMultiSelect: Boolean,
|
||||||
groupName: String,
|
groupName: String,
|
||||||
questionText: String,
|
questionText: String,
|
||||||
answers: Array,
|
answers: Array,
|
||||||
textPosition: {
|
textPosition: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "text-center",
|
default: "text-center",
|
||||||
},
|
},
|
||||||
selectingInitiatesLoad: Boolean,
|
selectingInitiatesLoad: Boolean,
|
||||||
loaderColor: {
|
loaderColor: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "blue",
|
default: "blue",
|
||||||
},
|
},
|
||||||
loaderPosition: {
|
loaderPosition: {
|
||||||
type: String,
|
type: String,
|
||||||
default: "right",
|
default: "right",
|
||||||
},
|
},
|
||||||
isRequired: Boolean,
|
isRequired: Boolean,
|
||||||
isOverflowScrollable: Boolean,
|
isOverflowScrollable: Boolean,
|
||||||
isWide: Boolean,
|
isWide: Boolean,
|
||||||
isCashOrInsurance: Boolean,
|
isCashOrInsurance: Boolean,
|
||||||
modelValue: [Array, Number, String],
|
modelValue: [Array, Number, String],
|
||||||
value: [Number, String],
|
value: [Number, String],
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
suppressError: Boolean,
|
suppressError: Boolean,
|
||||||
useTextForValue: Boolean,
|
useTextForValue: Boolean,
|
||||||
valueToLogType: String,
|
valueToLogType: String,
|
||||||
additionalButtonStyling: String,
|
additionalButtonStyling: String,
|
||||||
},
|
},
|
||||||
beforeMount() {
|
beforeMount() {
|
||||||
if (this.buttonTypeObject) {
|
if (this.buttonTypeObject) {
|
||||||
this.$options.components[this.buttonTypeString] = this.buttonTypeObject;
|
this.$options.components[this.buttonTypeString] = this.buttonTypeObject;
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
lastValuePushedToGa: null,
|
|
||||||
};
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
getFieldSetClasses() {
|
|
||||||
if (this.isOverflowScrollable) {
|
|
||||||
return "container-fluid overflow-scroll position-absolute px-5 pt-1 py-0";
|
|
||||||
}
|
}
|
||||||
else if (this.buttonTypeString === "listCard") {
|
},
|
||||||
return "w-100";
|
data() {
|
||||||
}
|
return {
|
||||||
else {
|
lastValuePushedToGa: null,
|
||||||
return "";
|
};
|
||||||
}
|
},
|
||||||
},
|
computed: {
|
||||||
getComponentLoopWrapperClasses() {
|
getFieldSetClasses() {
|
||||||
let classes;
|
if (this.isOverflowScrollable) {
|
||||||
switch (this.buttonTypeString) {
|
return "container-fluid overflow-scroll position-absolute px-5 pt-1 py-0";
|
||||||
case "listButton":
|
} else if (this.buttonTypeString == "listCard") {
|
||||||
classes = "w-100";
|
return "w-100";
|
||||||
break;
|
} else {
|
||||||
case "listButtonHorizontal":
|
return "";
|
||||||
classes = "d-flex flex-row p-0";
|
}
|
||||||
break;
|
},
|
||||||
case "listCard":
|
getComponentLoopWrapperClasses() {
|
||||||
classes = "row g-2 justify-content-center";
|
let classes;
|
||||||
if (this.isWide) {
|
switch (this.buttonTypeString) {
|
||||||
classes += " flex-column";
|
case "listButton":
|
||||||
}
|
classes = "w-100";
|
||||||
break;
|
break;
|
||||||
case "radio":
|
case "listButtonHorizontal":
|
||||||
classes = "ui-radio d-flex";
|
classes = "d-flex flex-row p-0";
|
||||||
break;
|
break;
|
||||||
case "servicePackageRadio":
|
case "listCard":
|
||||||
classes = "package-main";
|
classes = "row g-2 justify-content-center";
|
||||||
break;
|
if (this.isWide) {
|
||||||
}
|
classes += " flex-column";
|
||||||
return classes;
|
}
|
||||||
},
|
break;
|
||||||
getComponentWrapperClasses() {
|
case "radio":
|
||||||
let classes = "";
|
classes = "ui-radio d-flex";
|
||||||
|
break;
|
||||||
|
case "servicePackageRadio":
|
||||||
|
classes = "package-main";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return classes;
|
||||||
|
},
|
||||||
|
getComponentWrapperClasses() {
|
||||||
|
let classes = "";
|
||||||
|
|
||||||
classes += this.isWide ? "col-12" : "col";
|
classes += this.isWide ? "col-12" : "col";
|
||||||
|
|
||||||
if (this.buttonTypeString == "radio") {
|
if (this.buttonTypeString == "radio") {
|
||||||
classes += " radio-button-container";
|
classes += " radio-button-container";
|
||||||
} else if (this.buttonTypeString == "servicePackageRadio") {
|
} else if (this.buttonTypeString == "servicePackageRadio") {
|
||||||
classes = "package-wrapper";
|
classes = "package-wrapper";
|
||||||
}
|
}
|
||||||
|
|
||||||
return classes;
|
return classes;
|
||||||
},
|
},
|
||||||
buttonsInfo() {
|
buttonsInfo() {
|
||||||
return (Array.isArray(this.answers) ? this.answers : [])?.map((answer) => ({
|
return (Array.isArray(this.answers) ? this.answers : [])?.map((answer) => ({
|
||||||
buttonLabel: answer.buttonLabel ?? answer.Text ?? answer,
|
buttonLabel: answer.buttonLabel ?? answer.Text ?? answer,
|
||||||
altText: answer.altText ?? (answer.Name ? answer.Name : answer),
|
altText: answer.altText ?? (answer.Name ? answer.Name : answer),
|
||||||
buttonLabelSubCopy: answer.buttonLabelSubCopy ?? answer.SubText,
|
buttonLabelSubCopy: answer.buttonLabelSubCopy ?? answer.SubText,
|
||||||
buttonBodyCopy: answer.buttonBodyCopy ?? answer.buttonBodyCopy,
|
buttonBodyCopy: answer.buttonBodyCopy ?? answer.buttonBodyCopy,
|
||||||
buttonAuxillaryCopy: answer.buttonAuxillaryCopy ?? answer.buttonAuxillaryCopy,
|
buttonAuxillaryCopy: answer.buttonAuxillaryCopy ?? answer.buttonAuxillaryCopy,
|
||||||
buttonFooterCopy: answer.buttonFooterCopy ?? answer.buttonFooterCopy,
|
buttonFooterCopy: answer.buttonFooterCopy ?? answer.buttonFooterCopy,
|
||||||
buttonImage: answer.buttonImage ?? answer.AnswerImageUrl,
|
buttonImage: answer.buttonImage ?? answer.AnswerImageUrl,
|
||||||
buttonImageId: answer.buttonImageId ?? answer.ImageId,
|
buttonImageId: answer.buttonImageId ?? answer.ImageId,
|
||||||
groupName: this.formatString(this.groupName),
|
groupName: this.formatString(this.groupName),
|
||||||
value:
|
value:
|
||||||
answer.value ??
|
answer.value ??
|
||||||
(this.useTextForValue && answer.Text ? answer.Text : answer.Name) ??
|
(this.useTextForValue && answer.Text ? answer.Text : answer.Name) ??
|
||||||
(typeof answer !== "object" ? answer : null),
|
(typeof answer !== "object" ? answer : null),
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
selectedValues: {
|
selectedValues: {
|
||||||
get() {
|
get() {
|
||||||
return this.modelValue;
|
return this.modelValue;
|
||||||
},
|
},
|
||||||
set(selectedAnswers) {
|
set(selectedAnswers) {
|
||||||
this.$emit("update:modelValue", selectedAnswers);
|
this.$emit("update:modelValue", selectedAnswers);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
formatString(str) {
|
formatString(str) {
|
||||||
return String(str).replaceAll(" ", "-");
|
return String(str).replaceAll(" ", "-");
|
||||||
},
|
},
|
||||||
setLastValuePushedToGa(lastValuePushedToGa) {
|
setLastValuePushedToGa(lastValuePushedToGa) {
|
||||||
this.lastValuePushedToGa = lastValuePushedToGa;
|
this.lastValuePushedToGa = lastValuePushedToGa;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
listButton,
|
listButton,
|
||||||
listButtonHorizontal,
|
listButtonHorizontal,
|
||||||
listCard,
|
listCard,
|
||||||
ErrorMessage,
|
ErrorMessage,
|
||||||
radio,
|
radio,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.button-question-overflow {
|
.button-question-overflow {
|
||||||
height: calc(100vh - 274px);
|
height: calc(100vh - 274px);
|
||||||
|
|
||||||
.overflow-scroll {
|
.overflow-scroll {
|
||||||
// Height will be determined by overall height of content above list
|
// Height will be determined by overall height of content above list
|
||||||
height: calc(100% - 314px);
|
height: calc(100% - 314px);
|
||||||
overflow-x: hidden !important;
|
overflow-x: hidden !important;
|
||||||
-webkit-overflow-scrolling: touch;
|
-webkit-overflow-scrolling: touch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.button-question {
|
.button-question {
|
||||||
color: $black;
|
color: $black;
|
||||||
|
|
||||||
.radio-button-container {
|
.radio-button-container {
|
||||||
&:not(:last-child) {
|
&:not(:last-child) {
|
||||||
padding-bottom: map-get($spacers, 2);
|
padding-bottom: map-get($spacers, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.question-text {
|
.question-text {
|
||||||
margin-top: 1.5rem;
|
margin-top: 1.5rem;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 1.625rem;
|
line-height: 1.625rem;
|
||||||
|
|
||||||
& > span {
|
& > span {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vehicle-parts {
|
.vehicle-parts {
|
||||||
.question-text {
|
.question-text {
|
||||||
span {
|
span {
|
||||||
font-size: 0.875rem;
|
font-size: 0.875rem;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
margin: 0 0 0.5rem 0;
|
margin: 0 0 0.5rem 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.question-text {
|
.question-text {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
fieldset {
|
fieldset {
|
||||||
.ui-radio {
|
.ui-radio {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.welcome {
|
.welcome {
|
||||||
|
|
|
||||||
|
|
@ -1,159 +1,164 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="dropdown-question" :class="(errors && errors.length) || hasError ? 'has-error' : ''">
|
<div class="dropdown-question" :class="(errors && errors.length) || hasError ? 'has-error' : ''">
|
||||||
<label :for="inputId" :aria-label="questionText" class="form-label" v-html="labelText"></label>
|
<label
|
||||||
<select v-model="selectedOption"
|
:for="inputId"
|
||||||
class="form-select"
|
:aria-label="questionText"
|
||||||
:id="inputId"
|
class="form-label"
|
||||||
:name="inputId"
|
v-html="labelText"></label>
|
||||||
:aria-disabled="isDisabled"
|
<select
|
||||||
:disabled="isDisabled"
|
v-model="selectedOption"
|
||||||
:aria-required="isRequired"
|
class="form-select"
|
||||||
:validationRules="validationRules"
|
:id="inputId"
|
||||||
:placeHolderText="placeHolderText"
|
:name="inputId"
|
||||||
>
|
:aria-disabled="isDisabled"
|
||||||
<option v-if="placeHolderText" value="" selected>{{ placeHolderText }}</option>
|
:disabled="isDisabled"
|
||||||
<option v-for="(value, name, index) in options" :value="name" :key="index">
|
:aria-required="isRequired"
|
||||||
{{ value }}
|
:validationRules="validationRules"
|
||||||
</option>
|
:placeHolderText="placeHolderText">
|
||||||
</select>
|
<option v-if="placeHolderText" value="" selected>{{ placeHolderText }}</option>
|
||||||
<div v-show="errorMessage" class="row mt-2 form-test-error">
|
<option v-for="(value, name, index) in options" :value="name" :key="index">
|
||||||
<span role="alert">{{ errorMessage }}</span>
|
{{ value }}
|
||||||
</div>
|
</option>
|
||||||
</div>
|
</select>
|
||||||
|
<div v-show="errorMessage" class="row mt-2 form-test-error">
|
||||||
|
<span role="alert">{{ errorMessage }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { useField } from "vee-validate";
|
import { useField } from "vee-validate";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "dropdown-question",
|
name: "dropdown-question",
|
||||||
props: {
|
props: {
|
||||||
modelValue: String,
|
modelValue: String,
|
||||||
inputId: String,
|
inputId: String,
|
||||||
options: {
|
options: {
|
||||||
type: Object,
|
type: Object,
|
||||||
required: true
|
required: true,
|
||||||
},
|
},
|
||||||
isDisabled: Boolean,
|
isDisabled: Boolean,
|
||||||
isRequired: Boolean,
|
isRequired: Boolean,
|
||||||
disableAutoFill: Boolean,
|
disableAutoFill: Boolean,
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
cmsWidgetName: String,
|
cmsWidgetName: String,
|
||||||
hasError: Boolean,
|
hasError: Boolean,
|
||||||
errors: Array,
|
errors: Array,
|
||||||
placeHolderText: String
|
placeHolderText: String
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const propsClone = Object.assign({}, props);
|
const propsClone = Object.assign({}, props);
|
||||||
const modelValue = propsClone.modelValue;
|
const modelValue = propsClone.modelValue;
|
||||||
let initialValue;
|
let initialValue;
|
||||||
|
|
||||||
switch (typeof modelValue) {
|
switch (typeof modelValue) {
|
||||||
case "number":
|
case "number":
|
||||||
initialValue = modelValue;
|
initialValue = modelValue;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
initialValue = (modelValue && modelValue.length > 0) ? modelValue : "";
|
initialValue = (modelValue && modelValue.length > 0) ? modelValue : "";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const fieldOptions = {
|
const fieldOptions = {
|
||||||
type: "select",
|
type: "select",
|
||||||
value: props.modelValue,
|
value: props.modelValue,
|
||||||
initialValue: initialValue,
|
initialValue: initialValue,
|
||||||
};
|
};
|
||||||
|
|
||||||
const {
|
const {errorMessage, handleBlur, handleChange, meta, errors } = useField(
|
||||||
errorMessage,
|
props.inputId,
|
||||||
handleBlur,
|
props.validationRules,
|
||||||
handleChange,
|
fieldOptions
|
||||||
meta,
|
);
|
||||||
errors
|
|
||||||
} = useField(props.inputId, props.validationRules, fieldOptions);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
errorMessage,
|
errorMessage,
|
||||||
handleBlur,
|
handleBlur,
|
||||||
handleChange,
|
handleChange,
|
||||||
meta,
|
meta,
|
||||||
errors
|
errors
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
questionText(){
|
questionText() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
return this.getCmsContent(this.cmsWidgetName, "QuestionText");
|
||||||
},
|
},
|
||||||
selectedOption: {
|
selectedOption: {
|
||||||
get: function() {
|
get: function () {
|
||||||
return !this.modelValue ? "" : this.modelValue;
|
return !this.modelValue ? "" : this.modelValue;
|
||||||
},
|
},
|
||||||
set: function(newValue) {
|
set: function (newValue) {
|
||||||
this.$emit("update:modelValue", newValue);
|
this.$emit("update:modelValue", newValue);
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
labelText: {
|
labelText: {
|
||||||
get: function () {
|
get: function () {
|
||||||
const noBreakChar = "⁠";
|
const noBreakChar = "⁠";
|
||||||
var questionText = "";
|
var questionText = "";
|
||||||
if (this.disableAutoFill) {
|
if (this.disableAutoFill) {
|
||||||
var words = this.questionText.toString().split(/[ ]+/);
|
var words = this.questionText.toString().split(/[ ]+/);
|
||||||
words.forEach(function (word) {
|
words.forEach(function (word) {
|
||||||
const position = 1;
|
const position = 1;
|
||||||
word = [word.toString().slice(0, position), noBreakChar, word.toString().slice(position)].join('');
|
word = [
|
||||||
questionText += `${word} `;
|
word.toString().slice(0, position),
|
||||||
});
|
noBreakChar,
|
||||||
|
word.toString().slice(position),
|
||||||
questionText = questionText.trimEnd();
|
].join("");
|
||||||
} else {
|
questionText += `${word} `;
|
||||||
questionText = this.questionText.toString();
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return questionText;
|
questionText = questionText.trimEnd();
|
||||||
}
|
} else {
|
||||||
}
|
questionText = this.questionText.toString();
|
||||||
},
|
}
|
||||||
watch: {
|
|
||||||
selectedOption(newValue) {
|
return questionText;
|
||||||
this.handleChange(newValue);
|
},
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
|
watch: {
|
||||||
|
selectedOption(newValue) {
|
||||||
|
this.handleChange(newValue);
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.dropdown-question {
|
.dropdown-question {
|
||||||
label {
|
label {
|
||||||
color: $black;
|
color: $black;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
}
|
}
|
||||||
.form-label {
|
.form-label {
|
||||||
margin-bottom: .25rem;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
.form-select {
|
.form-select {
|
||||||
color: $gray-600;
|
color: $gray-600;
|
||||||
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 8.89' xml:space='preserve'%3e%3cpath d='M8 8.89c-.24 0-.46-.09-.63-.26L.26 1.53a.901.901 0 0 1 0-1.27C.43.1.66 0 .9 0s.47.1.64.26L8 6.74 14.47.27c.17-.17.4-.27.64-.27s.47.1.63.27c.17.17.26.4.26.64s-.1.47-.27.63l-7.1 7.09a.86.86 0 0 1-.63.26z' fill='%231474a2'/%3e%3c/svg%3e");
|
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 8.89' xml:space='preserve'%3e%3cpath d='M8 8.89c-.24 0-.46-.09-.63-.26L.26 1.53a.901.901 0 0 1 0-1.27C.43.1.66 0 .9 0s.47.1.64.26L8 6.74 14.47.27c.17-.17.4-.27.64-.27s.47.1.63.27c.17.17.26.4.26.64s-.1.47-.27.63l-7.1 7.09a.86.86 0 0 1-.63.26z' fill='%231474a2'/%3e%3c/svg%3e");
|
||||||
border: 1px solid $gray-500;
|
border: 1px solid $gray-500;
|
||||||
border-radius: .5rem;
|
border-radius: 0.5rem;
|
||||||
min-height: 3rem;
|
min-height: 3rem;
|
||||||
&:focus,
|
&:focus,
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
box-shadow: 0 0 0 2.5px $blue;
|
box-shadow: 0 0 0 2.5px $blue;
|
||||||
}
|
}
|
||||||
&:disabled,
|
&:disabled,
|
||||||
&.disabled {
|
&.disabled {
|
||||||
background-color: $gray-100;
|
background-color: $gray-100;
|
||||||
filter: grayscale(100%);
|
filter: grayscale(100%);
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: 0 0 0 4px transparent;
|
box-shadow: 0 0 0 4px transparent;
|
||||||
border: 1px solid $gray-500;
|
border: 1px solid $gray-500;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
border: 1px solid $gray-500;
|
border: 1px solid $gray-500;
|
||||||
box-shadow: 0 0 0 4px $blue-300;
|
box-shadow: 0 0 0 4px $blue-300;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<div
|
<div
|
||||||
class="modal fade modal-component"
|
class="modal fade modal-component"
|
||||||
v-on="{ 'hidden.bs.modal': resetButtonStyle }"
|
v-on="{ 'hidden.bs.modal': resetButtonStyle }"
|
||||||
:id="this.cmsWidgetName"
|
:id="cmsWidgetName"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
aria-labelledby="ModalComponentLabel"
|
aria-labelledby="ModalComponentLabel"
|
||||||
aria-hidden="true">
|
aria-hidden="true">
|
||||||
|
|
@ -17,13 +17,18 @@
|
||||||
aria-label="Close"></button>
|
aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body ps-4 pe-4 pt-5 pb-4">
|
<div class="modal-body ps-4 pe-4 pt-5 pb-4">
|
||||||
<img :src="this.ModalImage" class="mw-100 d-flex mx-auto mb-4" alt="" />
|
<img :src="ModalImage" class="mw-100 d-flex mx-auto mb-4" alt="" />
|
||||||
<h5 class="mb-4" v-html="this.ModalHeadline"></h5>
|
<h5 class="mb-4" v-html="ModalHeadline"></h5>
|
||||||
<p class="fw-bold mb-2 subheader-text" v-html="this.ModalSubheadertext"></p>
|
<p class="fw-bold mb-2 subheader-text" v-html="ModalSubheadertext"></p>
|
||||||
<p class="mb-0" v-html="this.ModalBodyText"></p>
|
<p class="mb-0" v-html="ModalBodyText"></p>
|
||||||
|
<p
|
||||||
|
class="my-4 caption modal-sub-body"
|
||||||
|
v-if="ModalSubBodyText"
|
||||||
|
v-html="ModalSubBodyText"></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer px-5 py-4">
|
<div class="modal-footer px-5 py-4">
|
||||||
<buttonMain
|
<buttonMain
|
||||||
|
isPrimary
|
||||||
class="w-100"
|
class="w-100"
|
||||||
ref="buttonMain"
|
ref="buttonMain"
|
||||||
suppressLoader
|
suppressLoader
|
||||||
|
|
@ -54,6 +59,9 @@ export default {
|
||||||
ModalBodyText() {
|
ModalBodyText() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, "BodyText");
|
return this.getCmsContent(this.cmsWidgetName, "BodyText");
|
||||||
},
|
},
|
||||||
|
ModalSubBodyText() {
|
||||||
|
return this.getCmsContent(this.cmsWidgetName, "BodyText2");
|
||||||
|
},
|
||||||
ModalImage() {
|
ModalImage() {
|
||||||
return this.getCmsContent(this.cmsWidgetName, "Image");
|
return this.getCmsContent(this.cmsWidgetName, "Image");
|
||||||
},
|
},
|
||||||
|
|
@ -97,6 +105,9 @@ export default {
|
||||||
box-shadow: 0px 16px 48px -16px rgba(0, 0, 0, 0.25);
|
box-shadow: 0px 16px 48px -16px rgba(0, 0, 0, 0.25);
|
||||||
border-radius: 1.5rem 1.5rem 0 0;
|
border-radius: 1.5rem 1.5rem 0 0;
|
||||||
.modal-body {
|
.modal-body {
|
||||||
|
.modal-sub-body {
|
||||||
|
color: $gray-600;
|
||||||
|
}
|
||||||
ul {
|
ul {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
@ -130,4 +141,4 @@ body {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<div
|
<div
|
||||||
class="text-block d-flex w-100 mt-2"
|
class="text-block w-100 mt-2"
|
||||||
:class="[justifyText, typeStyle, fontWeight]"
|
:class="[justifyText, typeStyle, fontWeight]"
|
||||||
v-html="this.TextBlockCopy"></div>
|
v-html="this.TextBlockCopy"></div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@
|
||||||
<button v-if="includeSelectIcon" type="submit" data-bs-toggle="modal"
|
<button v-if="includeSelectIcon" type="submit" data-bs-toggle="modal"
|
||||||
:data-bs-target="'#' + this.cmsWidgetName" aria-label="Select button" />
|
:data-bs-target="'#' + this.cmsWidgetName" aria-label="Select button" />
|
||||||
</div>
|
</div>
|
||||||
<div v-show="errorMessage" class="row my-2 form-test-error mb-0">
|
<div v-show="errorMessage" class="row my-1 form-test-error">
|
||||||
<span class="d-inline-flex mt-0" role="alert">{{ errorMessage }}</span>
|
<span class="d-inline-flex small mt-0" role="alert">{{ errorMessage }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ describe("address-questions.vue", () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("initial state", () => {
|
describe("initial state", () => {
|
||||||
test("Should render addressQuestions sub-components (textbox-questions and dropdown-questions)", async () => {
|
test("Should hide addressQuestions sub-components (textbox-questions and dropdown-questions)", async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
|
@ -24,17 +24,16 @@ describe("address-questions.vue", () => {
|
||||||
const city = wrapper.findComponent({ ref: "city" });
|
const city = wrapper.findComponent({ ref: "city" });
|
||||||
const state = wrapper.findComponent({ ref: "state" });
|
const state = wrapper.findComponent({ ref: "state" });
|
||||||
const zipCode = wrapper.findComponent({ ref: "zipCode" });
|
const zipCode = wrapper.findComponent({ ref: "zipCode" });
|
||||||
|
const streetAddress2 = wrapper.findComponent({ ref: "streetAddress2"});
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
expect(streetAddress.exists()).toBe(true);
|
expect(streetAddress.exists()).toBe(true);
|
||||||
expect(city.exists()).toBe(true);
|
expect(city.exists()).toBe(false);
|
||||||
expect(state.exists()).toBe(true);
|
expect(state.exists()).toBe(false);
|
||||||
expect(zipCode.exists()).toBe(true);
|
expect(zipCode.exists()).toBe(false);
|
||||||
|
expect(streetAddress2.exists()).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("happy paths", () => {
|
|
||||||
test("full street address is passed in => address fields are displayed", async () => {
|
test("full street address is passed in => address fields are displayed", async () => {
|
||||||
// Arrange/Act
|
// Arrange/Act
|
||||||
const { wrapper } = setupMocks({
|
const { wrapper } = setupMocks({
|
||||||
|
|
@ -45,6 +44,7 @@ describe("address-questions.vue", () => {
|
||||||
state: "OH",
|
state: "OH",
|
||||||
zipCode: "12312",
|
zipCode: "12312",
|
||||||
},
|
},
|
||||||
|
includeStreetAddress2: true,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -54,14 +54,40 @@ describe("address-questions.vue", () => {
|
||||||
const cityField = wrapper.findComponent({ ref: "city" });
|
const cityField = wrapper.findComponent({ ref: "city" });
|
||||||
const stateField = wrapper.findComponent({ ref: "state" });
|
const stateField = wrapper.findComponent({ ref: "state" });
|
||||||
const zipField = wrapper.findComponent({ ref: "zipCode" });
|
const zipField = wrapper.findComponent({ ref: "zipCode" });
|
||||||
|
const streetAddress2 = wrapper.findComponent({ ref: "streetAddress2"});
|
||||||
|
|
||||||
expect(cityField.exists()).toBeTruthy();
|
expect(cityField.exists()).toBeTruthy();
|
||||||
expect(cityField.isVisible()).toBeTruthy();
|
expect(cityField.isVisible()).toBeTruthy();
|
||||||
expect(stateField.exists()).toBeTruthy();
|
expect(stateField.exists()).toBeTruthy();
|
||||||
expect(cityField.isVisible()).toBeTruthy();
|
expect(cityField.isVisible()).toBeTruthy();
|
||||||
expect(zipField.exists()).toBeTruthy();
|
expect(zipField.exists()).toBeTruthy();
|
||||||
expect(cityField.isVisible()).toBeTruthy();
|
expect(cityField.isVisible()).toBeTruthy();
|
||||||
|
expect(streetAddress2.isVisible()).toBeTruthy();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("address2 is hidden if includeStreetAddress2 is false", async () => {
|
||||||
|
// Arrange/Act
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
props: {
|
||||||
|
modelValue: {
|
||||||
|
streetAddress: "12345 Test Road",
|
||||||
|
city: "Tests",
|
||||||
|
state: "OH",
|
||||||
|
zipCode: "12312",
|
||||||
|
},
|
||||||
|
includeStreetAddress2: false,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
const streetAddress2 = wrapper.findComponent({ ref: "streetAddress2"});
|
||||||
|
expect(streetAddress2.exists()).toBe(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("happy paths", () => {
|
||||||
test("street address is entered, user chooses good result from autocomplete results => other fields are filled in", async () => {
|
test("street address is entered, user chooses good result from autocomplete results => other fields are filled in", async () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const { wrapper } = setupMocks({});
|
const { wrapper } = setupMocks({});
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@
|
||||||
cmsWidgetName="AlertNoMatchWarningWidget"
|
cmsWidgetName="AlertNoMatchWarningWidget"
|
||||||
alertClass="alert-warning"
|
alertClass="alert-warning"
|
||||||
v-bind:isDismissible="false" />
|
v-bind:isDismissible="false" />
|
||||||
|
|
||||||
<div class="row mt-2 mb-4">
|
<div class="row mt-2 mb-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
|
|
@ -31,55 +30,55 @@
|
||||||
@keydown.enter.prevent />
|
@keydown.enter.prevent />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-2 mb-4" v-if="includeStreetAddress2">
|
|
||||||
<div class="col">
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="StreetAddress2QuestionWidget"
|
|
||||||
v-model="addressModel.streetAddress2"
|
|
||||||
aria-haspopup=""
|
|
||||||
inputId="streetAddress2Field"
|
|
||||||
disableAutoFill
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<transition name="fade" mode="out-in">
|
<transition name="fade" mode="out-in">
|
||||||
<div class="row mb-4" aria-live="polite">
|
<div v-if="showAllFields">
|
||||||
<div class="col">
|
<div class="row mt-2 mb-4" v-if="includeStreetAddress2">
|
||||||
<textboxQuestion
|
<div class="col">
|
||||||
cmsWidgetName="CityQuestionWidget"
|
<textboxQuestion
|
||||||
v-model="addressModel.city"
|
ref="streetAddress2"
|
||||||
ref="city"
|
cmsWidgetName="StreetAddress2QuestionWidget"
|
||||||
inputId="cbf28188fdf2436688fd735915f7ee56"
|
v-model="addressModel.streetAddress2"
|
||||||
disableAutoFill
|
aria-haspopup=""
|
||||||
validationRules="city-required" />
|
inputId="streetAddress2Field"
|
||||||
|
disableAutoFill
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4" aria-live="polite">
|
||||||
|
<div class="col">
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="CityQuestionWidget"
|
||||||
|
v-model="addressModel.city"
|
||||||
|
ref="city"
|
||||||
|
inputId="cbf28188fdf2436688fd735915f7ee56"
|
||||||
|
disableAutoFill
|
||||||
|
validationRules="city-required" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row mb-4" aria-live="polite">
|
||||||
|
<div class="col">
|
||||||
|
<dropdownQuestion
|
||||||
|
cmsWidgetName="StateQuestionWidget"
|
||||||
|
v-model="addressModel.state"
|
||||||
|
ref="state"
|
||||||
|
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||||
|
:options="stateOptions"
|
||||||
|
disableAutoFill
|
||||||
|
validationRules="state-required" />
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<textboxQuestion
|
||||||
|
cmsWidgetName="ZipQuestionWidget"
|
||||||
|
v-model="addressModel.zipCode"
|
||||||
|
ref="zipCode"
|
||||||
|
inputId="01a9a1c2de0b4c9da8e023c9ae3be498"
|
||||||
|
mask="#####"
|
||||||
|
disableAutoFill
|
||||||
|
validationRules="zip-code-required|zip-code-format" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</transition>
|
</transition>
|
||||||
<transition name="fade" mode="out-in">
|
|
||||||
<div class="row mb-4" aria-live="polite">
|
|
||||||
<div class="col">
|
|
||||||
<dropdownQuestion
|
|
||||||
cmsWidgetName="StateQuestionWidget"
|
|
||||||
v-model="addressModel.state"
|
|
||||||
ref="state"
|
|
||||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
|
||||||
:options="stateOptions"
|
|
||||||
disableAutoFill
|
|
||||||
validationRules="state-required" />
|
|
||||||
</div>
|
|
||||||
<div class="col">
|
|
||||||
<textboxQuestion
|
|
||||||
cmsWidgetName="ZipQuestionWidget"
|
|
||||||
v-model="addressModel.zipCode"
|
|
||||||
ref="zipCode"
|
|
||||||
inputId="01a9a1c2de0b4c9da8e023c9ae3be498"
|
|
||||||
mask="#####"
|
|
||||||
disableAutoFill
|
|
||||||
validationRules="zip-code-required|zip-code-format" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
@ -130,6 +129,7 @@ export default {
|
||||||
matchFound: null, // null = no attempted match, true = match was found, false = match was not found
|
matchFound: null, // null = no attempted match, true = match was found, false = match was not found
|
||||||
enterPressed: false,
|
enterPressed: false,
|
||||||
isAddressWatchActive: false, // Only deep watch the address model when a match was not found
|
isAddressWatchActive: false, // Only deep watch the address model when a match was not found
|
||||||
|
showAllFields: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -210,6 +210,8 @@ export default {
|
||||||
// If a match has been previously found then do nothing
|
// If a match has been previously found then do nothing
|
||||||
// OR
|
// OR
|
||||||
// If the user pressed "Enter" then do nothing
|
// If the user pressed "Enter" then do nothing
|
||||||
|
this.showAllFields = true;
|
||||||
|
|
||||||
if (self.matchFound || self.enterPressed) {
|
if (self.matchFound || self.enterPressed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -307,6 +309,7 @@ export default {
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.setupAddressLookup();
|
this.setupAddressLookup();
|
||||||
|
this.showAllFields = !!this.addressModel.streetAddress;
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
matchFound: {
|
matchFound: {
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
v-model="licensePlate"
|
v-model="licensePlate"
|
||||||
isRequired
|
isRequired
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
|
id="license-plate-question-wrapper"
|
||||||
inputId="license-plate-question"
|
inputId="license-plate-question"
|
||||||
validationRules="license-plate-required" />
|
validationRules="license-plate-required" />
|
||||||
<dropdownQuestion
|
<dropdownQuestion
|
||||||
|
|
@ -272,3 +273,12 @@ export default {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#license-plate-question-wrapper .form-test-error {
|
||||||
|
/**
|
||||||
|
Override extra margin-bottom in the error message in TextboxQuestion
|
||||||
|
*/
|
||||||
|
margin-bottom: 0 !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
/* eslint-env jest */
|
/* eslint-env jest */
|
||||||
import { mount } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||||
|
import { issPageValues } from '@/router/router-constants/issPage-values';
|
||||||
|
import { queryStrings } from '@/constants/query-strings';
|
||||||
|
import { GaActions } from "@/constants/analytics";
|
||||||
import VehicleLookup from './vehicle-lookup.vue';
|
import VehicleLookup from './vehicle-lookup.vue';
|
||||||
|
|
||||||
const vinLookupMethodsMockData = {
|
const vinLookupMethodsMockData = {
|
||||||
|
|
@ -55,6 +58,12 @@ function setupMocks() {
|
||||||
mixins: [
|
mixins: [
|
||||||
{
|
{
|
||||||
computed: {
|
computed: {
|
||||||
|
GaActions() {
|
||||||
|
return GaActions;
|
||||||
|
},
|
||||||
|
queryStrings() {
|
||||||
|
return queryStrings;
|
||||||
|
},
|
||||||
navigationScenarios() {
|
navigationScenarios() {
|
||||||
return navigationScenarios;
|
return navigationScenarios;
|
||||||
},
|
},
|
||||||
|
|
@ -80,6 +89,7 @@ function setupMocks() {
|
||||||
}),
|
}),
|
||||||
getFooterInfoBoxHeight: jest.fn(() => 80),
|
getFooterInfoBoxHeight: jest.fn(() => 80),
|
||||||
getPageNameByQueryString: jest.fn(() => "vehicle-lookup"),
|
getPageNameByQueryString: jest.fn(() => "vehicle-lookup"),
|
||||||
|
pushEventToGA: jest.fn(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -2,12 +2,23 @@
|
||||||
import { render } from '@testing-library/vue';
|
import { render } from '@testing-library/vue';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import '@testing-library/jest-dom';
|
import '@testing-library/jest-dom';
|
||||||
|
import { issPageValues } from '@/router/router-constants/issPage-values';
|
||||||
|
import { queryStrings } from '@/constants/query-strings';
|
||||||
|
import { GaActions } from "@/constants/analytics";
|
||||||
import VinLocationInformationComponent from './vin-location-information.vue';
|
import VinLocationInformationComponent from './vin-location-information.vue';
|
||||||
|
|
||||||
const mockText = Object.freeze({
|
const mockText = Object.freeze({
|
||||||
HEADER: 'Mock Header',
|
HEADER: 'Mock Header',
|
||||||
BODY: 'Mock Body',
|
BODY: 'Mock Body',
|
||||||
});
|
});
|
||||||
|
const mockRoute = {
|
||||||
|
query: {
|
||||||
|
issPage: issPageValues.VIN_LOOKUP,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const mockRouter = {
|
||||||
|
navigate: jest.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
const mountOptions = {
|
const mountOptions = {
|
||||||
global: {
|
global: {
|
||||||
|
|
@ -27,9 +38,22 @@ const mountOptions = {
|
||||||
|
|
||||||
return '';
|
return '';
|
||||||
}),
|
}),
|
||||||
|
pushEventToGA: jest.fn()
|
||||||
},
|
},
|
||||||
|
computed: {
|
||||||
|
GaActions() {
|
||||||
|
return GaActions;
|
||||||
|
},
|
||||||
|
queryStrings() {
|
||||||
|
return queryStrings;
|
||||||
|
},
|
||||||
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
mocks: {
|
||||||
|
$route: mockRoute,
|
||||||
|
$router: mockRouter,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ import { createTestingPinia } from '@pinia/testing';
|
||||||
import userEvent from '@testing-library/user-event';
|
import userEvent from '@testing-library/user-event';
|
||||||
import { errorMessages } from '@/constants/error-messages';
|
import { errorMessages } from '@/constants/error-messages';
|
||||||
import { issPageValues } from '@/router/router-constants/issPage-values';
|
import { issPageValues } from '@/router/router-constants/issPage-values';
|
||||||
|
import { queryStrings } from '@/constants/query-strings';
|
||||||
|
import { GaActions } from "@/constants/analytics";
|
||||||
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||||
import { routerParams } from '@/router/router-params';
|
import { routerParams } from '@/router/router-params';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
|
|
@ -134,11 +136,18 @@ const mountOptions = {
|
||||||
getFooterInfoBoxHeight: jest.fn(() => 80),
|
getFooterInfoBoxHeight: jest.fn(() => 80),
|
||||||
cssClassNameForCmsWidget: jest.fn(() => 'widget-name-mock-class'),
|
cssClassNameForCmsWidget: jest.fn(() => 'widget-name-mock-class'),
|
||||||
getPageNameByQueryString: jest.fn(() => ''),
|
getPageNameByQueryString: jest.fn(() => ''),
|
||||||
|
pushEventToGA: jest.fn(),
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
GaActions() {
|
||||||
|
return GaActions;
|
||||||
|
},
|
||||||
navigationScenarios() {
|
navigationScenarios() {
|
||||||
return navigationScenarios;
|
return navigationScenarios;
|
||||||
},
|
},
|
||||||
|
queryStrings() {
|
||||||
|
return queryStrings;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
&.list-card {
|
&.list-card {
|
||||||
&:not(.selected) {
|
&:not(.selected) {
|
||||||
position: relative;
|
position: relative;
|
||||||
z-index: 4;
|
z-index: 5;
|
||||||
@include box-shadow-hover($blue-300);
|
@include box-shadow-hover($blue-300);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,10 +11,6 @@
|
||||||
{{text}}
|
{{text}}
|
||||||
<slot name="after-text"></slot>
|
<slot name="after-text"></slot>
|
||||||
</a>
|
</a>
|
||||||
<a v-else-if="linkType === 'dashedUnderline'" @click="handleClick" class="dashed-underline" :href="href">
|
|
||||||
{{text}}
|
|
||||||
<slot name="after-text"></slot>
|
|
||||||
</a>
|
|
||||||
<a v-else-if="linkType === 'text'" @click="handleClick" :href="href">
|
<a v-else-if="linkType === 'text'" @click="handleClick" :href="href">
|
||||||
{{text}}
|
{{text}}
|
||||||
<slot name="after-text"></slot>
|
<slot name="after-text"></slot>
|
||||||
|
|
@ -33,6 +29,12 @@
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleClick(event) {
|
handleClick(event) {
|
||||||
|
this.pushEventToGA(
|
||||||
|
this.$route.query[this.queryStrings.ISS_PAGE],
|
||||||
|
this.GaActions.CLICKED,
|
||||||
|
this.text,
|
||||||
|
true
|
||||||
|
);
|
||||||
this.$emit("click-event");
|
this.$emit("click-event");
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -41,10 +43,9 @@
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
a {
|
a {
|
||||||
display: inline-flex !important;
|
|
||||||
color: $blue;
|
color: $blue;
|
||||||
text-underline-offset: 0.5em;
|
text-underline-offset: 5px;
|
||||||
line-height: 26px;
|
line-height: 2;
|
||||||
padding: 0 0 4px 0;
|
padding: 0 0 4px 0;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
max-width: fit-content;
|
max-width: fit-content;
|
||||||
|
|
@ -75,9 +76,6 @@
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.dashed-underline {
|
|
||||||
text-decoration: underline dashed 1px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
Loading…
Reference in a new issue