Merge pull request #359 from Safelite/feature/digital/SSR-521
Adding Contact Details Page
This commit is contained in:
commit
c3a188bc7c
22 changed files with 2229 additions and 202 deletions
64
.eslintrc.js
64
.eslintrc.js
|
|
@ -1,21 +1,45 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: [
|
env: {
|
||||||
'eslint-config-airbnb-base',
|
browser: true,
|
||||||
'plugin:vue/vue3-strongly-recommended'
|
jest: true
|
||||||
],
|
},
|
||||||
rules: {
|
extends: [
|
||||||
'linebreak-style': 'off',
|
'eslint-config-airbnb-base',
|
||||||
'vue/component-definition-name-casing': ['warn', 'kebab-case'],
|
'plugin:vue/vue3-recommended'
|
||||||
'vue/require-default-prop': 'off',
|
],
|
||||||
'vue/attribute-hyphenation': ['warn', 'never'],
|
rules: {
|
||||||
'vue/v-on-event-hyphenation': ['warn', 'never']
|
'linebreak-style': 'off',
|
||||||
},
|
'vue/component-definition-name-casing': ['warn', 'kebab-case'],
|
||||||
settings: {
|
'vue/require-default-prop': 'off',
|
||||||
'import/resolver': {
|
'vue/attribute-hyphenation': ['warn', 'never'],
|
||||||
alias: {
|
'vue/v-on-event-hyphenation': ['warn', 'never'],
|
||||||
map: [['@', './src/']],
|
'object-curly-newline': ['error', { consistent: true }],
|
||||||
extensions: ['.js', '.vue']
|
'function-paren-newline': ['error', 'never'],
|
||||||
}
|
'operator-linebreak': ['error', 'before'],
|
||||||
|
'implicit-arrow-linebreak': ['error', 'below'],
|
||||||
|
'comma-dangle': ['error', 'never'],
|
||||||
|
indent: ['error', 4],
|
||||||
|
'vue/html-indent': 'off',
|
||||||
|
'vue/html-closing-bracket-newline': ['error', {
|
||||||
|
singleline: 'never',
|
||||||
|
multiline: 'never'
|
||||||
|
}],
|
||||||
|
'vue/html-self-closing': ['error', {
|
||||||
|
html: {
|
||||||
|
void: 'any',
|
||||||
|
normal: 'any',
|
||||||
|
component: 'any'
|
||||||
|
},
|
||||||
|
svg: 'always',
|
||||||
|
math: 'always'
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
settings: {
|
||||||
|
'import/resolver': {
|
||||||
|
alias: {
|
||||||
|
map: [['@', './src/']],
|
||||||
|
extensions: ['.js', '.vue']
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
|
||||||
1036
package-lock.json
generated
1036
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -40,6 +40,7 @@
|
||||||
"eslint-plugin-vue": "9.8.0",
|
"eslint-plugin-vue": "9.8.0",
|
||||||
"jest": "^27.0.5",
|
"jest": "^27.0.5",
|
||||||
"sass": "^1.32.7",
|
"sass": "^1.32.7",
|
||||||
"sass-loader": "^12.0.0"
|
"sass-loader": "^12.0.0",
|
||||||
|
"vitest": "^0.32.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
22
src/constants/global-rules.js
Normal file
22
src/constants/global-rules.js
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
/**
|
||||||
|
* @file global-rules.js
|
||||||
|
* @author MB
|
||||||
|
* @copyright Safelite
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Contains all the globally defined rules.
|
||||||
|
*/
|
||||||
|
const globalRules = {
|
||||||
|
POLICYHOLDER_FIRST_NAME_REQUIRED: 'policyholder-first-name-required',
|
||||||
|
POLICYHOLDER_LAST_NAME_REQUIRED: 'policyholder-last-name-required',
|
||||||
|
FIRST_NAME_REQUIRED: 'first-name-required',
|
||||||
|
LAST_NAME_REQUIRED: 'last-name-required',
|
||||||
|
PHONE_NUMBER_REQUIRED: 'phone-number-required',
|
||||||
|
EMAIL_ADDRESS_REQUIRED: 'email-required',
|
||||||
|
EMAIL_ADDRESS_FORMAT: 'email-address-format',
|
||||||
|
PHONE_NUMBER_FORMAT: 'phone-number-format',
|
||||||
|
OPTION_REQUIRED: 'option-required'
|
||||||
|
};
|
||||||
|
|
||||||
|
export default globalRules;
|
||||||
|
|
@ -0,0 +1,348 @@
|
||||||
|
// Components
|
||||||
|
import textareaQuestion from '@/digital-components/textarea-question/textarea-question.vue';
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import { shallowMount } from '@vue/test-utils';
|
||||||
|
import { getRandomString, getRandomInt } from '@/helpers/data-generation';
|
||||||
|
import { nextTick } from 'vue';
|
||||||
|
import { defineRule } from 'vee-validate';
|
||||||
|
import { required } from '@/helpers/validation-rules';
|
||||||
|
|
||||||
|
describe('textarea-question.vue', () => {
|
||||||
|
const mockMixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn().mockImplementation(() =>
|
||||||
|
getRandomString(10, 20)),
|
||||||
|
setCmsContent: jest.fn()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
describe('Expected components rendered', () => {
|
||||||
|
test('Label rendered', () => {
|
||||||
|
// Arrange
|
||||||
|
const questionText = getRandomString(10, 20);
|
||||||
|
const mixinWithQuestion = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn().mockImplementation(() =>
|
||||||
|
questionText),
|
||||||
|
setCmsContent: jest.fn()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20)
|
||||||
|
},
|
||||||
|
mixins: [mixinWithQuestion]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const label = wrapper.find('label');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(label.exists()).toBe(true);
|
||||||
|
expect(wrapper.text()).toContain(questionText);
|
||||||
|
});
|
||||||
|
test('Textarea rendered', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20)
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const textarea = wrapper.find('textarea');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(textarea.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Character count rendered', () => {
|
||||||
|
// Arrange
|
||||||
|
const maxLength = getRandomInt(100, 900);
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
maxLength
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
const expected = `0/${maxLength}`;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.text()).toContain(expected);
|
||||||
|
});
|
||||||
|
test('Error rendered', async () => {
|
||||||
|
// Arrange
|
||||||
|
const maxLength = getRandomInt(100, 900);
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
maxLength
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const errorComponent = wrapper.find('#error-message');
|
||||||
|
expect(errorComponent.text()).toBe('');
|
||||||
|
|
||||||
|
const errorMessage = getRandomString(20, 30);
|
||||||
|
wrapper.vm.resetField({
|
||||||
|
errors: [errorMessage]
|
||||||
|
});
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(errorComponent.text()).toBe(errorMessage);
|
||||||
|
});
|
||||||
|
test('Not required => optional text rendered', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
isRequired: false
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.text()).toContain('Optional');
|
||||||
|
});
|
||||||
|
test('Required => optional text not rendered', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
isRequired: true
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.text()).not.toContain('Optional');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Computed properties rendered', () => {
|
||||||
|
describe('characterCount', () => {
|
||||||
|
test('Model value null => character count is 0 ', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
modelValue: null
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.characterCount).toBe(0);
|
||||||
|
});
|
||||||
|
test('Model value undefined => character count is 0', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
modelValue: undefined
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.characterCount).toBe(0);
|
||||||
|
});
|
||||||
|
test('Model value empty string => character count is 0', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
modelValue: ''
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.characterCount).toBe(0);
|
||||||
|
});
|
||||||
|
test('Model value non-empty string => character count is as expected', () => {
|
||||||
|
// Arrange
|
||||||
|
const length = getRandomInt(10, 30);
|
||||||
|
const value = getRandomString(length, length);
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
modelValue: value
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.characterCount).toBe(length);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('value', () => {
|
||||||
|
test('Get value corresponds to modelValue', () => {
|
||||||
|
// Arrange
|
||||||
|
const modelValue = getRandomString(10, 20);
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
modelValue
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.value).toBe(modelValue);
|
||||||
|
});
|
||||||
|
test('Set value => update modelValue event emitted with new value', () => {
|
||||||
|
// Arrange
|
||||||
|
const modelValue = getRandomString(10, 20);
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
modelValue
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
const newValue = getRandomString(10, 20);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.value = newValue;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.emitted('update:modelValue')).toBeTruthy();
|
||||||
|
expect(wrapper.emitted('update:modelValue')[0][0]).toEqual(newValue);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
describe('Properties properly affect initial state', () => {
|
||||||
|
test('Placeholder text sets placeholder text of text area', () => {
|
||||||
|
// Arrange
|
||||||
|
const placeholderText = getRandomString(10, 20);
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
placeholderText
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const textarea = wrapper.find('textarea');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(textarea.attributes().placeholder).toBe(placeholderText);
|
||||||
|
});
|
||||||
|
test('isDisabled true => textarea disabled', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
isDisabled: true
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const textarea = wrapper.find('textarea');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(textarea.attributes().disabled).toBeDefined();
|
||||||
|
});
|
||||||
|
test('isRequired true => textarea required', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
isRequired: true
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const textarea = wrapper.find('textarea');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(textarea.attributes().required).toBeDefined();
|
||||||
|
});
|
||||||
|
test('validationRules set rules of text area', () => {
|
||||||
|
// Arrange
|
||||||
|
const rule = getRandomString(10, 20);
|
||||||
|
const errorMessage = getRandomString(20, 30);
|
||||||
|
defineRule(rule, required(errorMessage));
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
validationRules: rule
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const textarea = wrapper.find('textarea');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(textarea.attributes().validationrules).toBe(rule);
|
||||||
|
});
|
||||||
|
test('maxLength set max length of text area', () => {
|
||||||
|
// Arrange
|
||||||
|
const maxLength = toString(getRandomInt(100, 900));
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
maxLength
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const textarea = wrapper.find('textarea');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(textarea.attributes().maxlength).toBe(maxLength);
|
||||||
|
});
|
||||||
|
test('inputRows set input rows of text area', () => {
|
||||||
|
// Arrange
|
||||||
|
const inputRows = getRandomInt(10, 20);
|
||||||
|
const wrapper = shallowMount(textareaQuestion, {
|
||||||
|
propsData: {
|
||||||
|
inputId: getRandomString(10, 20),
|
||||||
|
cmsWidgetName: getRandomString(10, 20),
|
||||||
|
inputRows
|
||||||
|
},
|
||||||
|
mixins: [mockMixin]
|
||||||
|
});
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const textarea = wrapper.find('textarea');
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(textarea.attributes().rows).toBe(`${inputRows}`);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
197
src/digital-components/textarea-question/textarea-question.vue
Normal file
197
src/digital-components/textarea-question/textarea-question.vue
Normal file
|
|
@ -0,0 +1,197 @@
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="textarea-question"
|
||||||
|
:class="(errors && errors.length) ? 'has-error' : ''">
|
||||||
|
<label
|
||||||
|
:for="inputId"
|
||||||
|
class="form-label">
|
||||||
|
{{ questionText }}
|
||||||
|
<span
|
||||||
|
v-if="!isRequired"
|
||||||
|
class="optional">(Optional)</span>
|
||||||
|
</label>
|
||||||
|
<div class="input-wrapper">
|
||||||
|
<textarea
|
||||||
|
:id="inputId"
|
||||||
|
:ref="inputId"
|
||||||
|
v-model.trim="value"
|
||||||
|
class="form-control"
|
||||||
|
:name="inputId"
|
||||||
|
:rows="[inputRows ?? 10]"
|
||||||
|
:placeholder="placeholderText"
|
||||||
|
:disabled="isDisabled"
|
||||||
|
:required="isRequired"
|
||||||
|
:maxlength="maxLength"
|
||||||
|
:validationRules="validationRules"
|
||||||
|
@change="validationRules ? handleChange : () => {}"
|
||||||
|
@blur="validationRules ? handleBlur : () => {}"
|
||||||
|
@paste="trimOnPaste"
|
||||||
|
@drop="trimOnPaste">
|
||||||
|
</textarea>
|
||||||
|
</div>
|
||||||
|
<p class="character-count margin-top-8">
|
||||||
|
{{ characterCount }}/{{ maxLength }} characters remaining
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
v-show="errorMessage"
|
||||||
|
id="error-message"
|
||||||
|
class="row my-1 form-test-error">
|
||||||
|
<span
|
||||||
|
class="d-inline-flex mt-0"
|
||||||
|
role="alert">{{ errorMessage }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { useField } from 'vee-validate';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'textarea-question',
|
||||||
|
props: {
|
||||||
|
placeholderText: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
inputId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
modelValue: String,
|
||||||
|
isDisabled: Boolean,
|
||||||
|
isRequired: Boolean,
|
||||||
|
validationRules: String,
|
||||||
|
cmsWidgetName: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
maxLength: {
|
||||||
|
type: String,
|
||||||
|
default: '300'
|
||||||
|
},
|
||||||
|
inputRows: Number
|
||||||
|
},
|
||||||
|
emits: ['update:modelValue'],
|
||||||
|
setup(props) {
|
||||||
|
const propsClone = { ...props };
|
||||||
|
const { modelValue } = propsClone;
|
||||||
|
const initialValue = modelValue ?? '';
|
||||||
|
|
||||||
|
const fieldOptions = {
|
||||||
|
type: 'text',
|
||||||
|
value: modelValue,
|
||||||
|
initialValue
|
||||||
|
};
|
||||||
|
|
||||||
|
const { errorMessage,
|
||||||
|
handleChange,
|
||||||
|
handleBlur,
|
||||||
|
validate,
|
||||||
|
errors,
|
||||||
|
resetField }
|
||||||
|
= useField(props.inputId,
|
||||||
|
props.validationRules,
|
||||||
|
fieldOptions);
|
||||||
|
|
||||||
|
return {
|
||||||
|
errorMessage,
|
||||||
|
handleChange,
|
||||||
|
handleBlur,
|
||||||
|
validate,
|
||||||
|
errors,
|
||||||
|
resetField
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
/**
|
||||||
|
* @summary Returns the number of characters in the textarea field.
|
||||||
|
*/
|
||||||
|
characterCount() {
|
||||||
|
return this?.modelValue?.length ?? 0;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @summary Returns the CMS text associated with the question.
|
||||||
|
*/
|
||||||
|
questionText() {
|
||||||
|
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
get() {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set(newValue) {
|
||||||
|
this.$emit('update:modelValue', newValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
/**
|
||||||
|
* @summary Removes whitespace from the end of pasted content.
|
||||||
|
*/
|
||||||
|
trimOnPaste(evt) {
|
||||||
|
evt.stopPropagation();
|
||||||
|
evt.preventDefault();
|
||||||
|
|
||||||
|
const data = evt.type === 'paste' ? (evt.clipboardData || window.clipboardData) : evt.dataTransfer;
|
||||||
|
const value = data.getData('Text')?.trim();
|
||||||
|
|
||||||
|
this.$emit('update:modelValue', value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.textarea-question {
|
||||||
|
label {
|
||||||
|
color: $black;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
.form-test-error span{
|
||||||
|
color: $red;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.form-control {
|
||||||
|
max-height: 30rem;
|
||||||
|
border: 1px solid $gray-500;
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
padding: 12px 16px;
|
||||||
|
&::placeholder {
|
||||||
|
color: $gray-500;
|
||||||
|
}
|
||||||
|
&:focus {
|
||||||
|
box-shadow: 0 0 0 2.5px $blue;
|
||||||
|
}
|
||||||
|
&:disabled,
|
||||||
|
&.disabled {
|
||||||
|
background-color: $gray-100;
|
||||||
|
&:hover {
|
||||||
|
box-shadow: 0 0 0 4px transparent;
|
||||||
|
border: 1px solid $gray-500;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
border: 1px solid $gray-500;
|
||||||
|
box-shadow: 0 0 0 4px $blue-300;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.optional {
|
||||||
|
color: $gray-550;
|
||||||
|
}
|
||||||
|
|
||||||
|
.character-count {
|
||||||
|
color: $gray-600;
|
||||||
|
font-size: 12px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-top-8 {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
47
src/helpers/global-rule-definer.js
Normal file
47
src/helpers/global-rule-definer.js
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
import { defineRule } from 'vee-validate';
|
||||||
|
import { errorMessages } from '@/constants/error-messages';
|
||||||
|
import globalRules from '@/constants/global-rules';
|
||||||
|
import { required, regex } from '@/helpers/validation-rules';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Define global rules related to names
|
||||||
|
*/
|
||||||
|
function defineGlobalNameRules() {
|
||||||
|
defineRule(globalRules.FIRST_NAME_REQUIRED, required(errorMessages.FIRST_NAME_REQUIRED));
|
||||||
|
defineRule(globalRules.LAST_NAME_REQUIRED, required(errorMessages.LAST_NAME_REQUIRED));
|
||||||
|
defineRule(globalRules.POLICYHOLDER_FIRST_NAME_REQUIRED,
|
||||||
|
required(errorMessages.POLICYHOLDER_FIRST_NAME_REQUIRED));
|
||||||
|
defineRule(globalRules.POLICYHOLDER_LAST_NAME_REQUIRED,
|
||||||
|
required(errorMessages.POLICYHOLDER_LAST_NAME_REQUIRED));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Define global rules related to email addresses
|
||||||
|
*/
|
||||||
|
function defineGlobalEmailRules() {
|
||||||
|
defineRule(globalRules.EMAIL_ADDRESS_REQUIRED, required(errorMessages.EMAIL_ADDRESS_REQUIRED));
|
||||||
|
defineRule(globalRules.EMAIL_ADDRESS_FORMAT,
|
||||||
|
regex(/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,})$/,
|
||||||
|
errorMessages.EMAIL_ADDRESS_FORMAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Define global rules related to phone numbers
|
||||||
|
*/
|
||||||
|
function defineGlobalPhoneNumberRules() {
|
||||||
|
defineRule(globalRules.PHONE_NUMBER_REQUIRED, required(errorMessages.PHONE_NUMBER_REQUIRED));
|
||||||
|
defineRule(globalRules.PHONE_NUMBER_FORMAT,
|
||||||
|
regex(/^(\([0-9]{3}\)|[0-9]{3}) *[-.]? *[0-9]{3} *[-.]? *[0-9]{4}$/,
|
||||||
|
errorMessages.PHONE_NUMBER_FORMAT));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Define all global rules
|
||||||
|
*/
|
||||||
|
export default function defineGlobalRules() {
|
||||||
|
defineGlobalNameRules();
|
||||||
|
defineGlobalEmailRules();
|
||||||
|
defineGlobalPhoneNumberRules();
|
||||||
|
|
||||||
|
defineRule(globalRules.OPTION_REQUIRED, required(errorMessages.OPTION_REQUIRED));
|
||||||
|
}
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
ref="firstName"
|
ref="firstName"
|
||||||
inputId="08497a2efd9a4a73a70360ab47b4838d"
|
inputId="08497a2efd9a4a73a70360ab47b4838d"
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
validationRules="first-name-required" />
|
:validationRules="rules.firstName" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
|
|
@ -19,21 +19,15 @@
|
||||||
ref="lastName"
|
ref="lastName"
|
||||||
inputId="0030e56a57e74a4ab92de7fb8e97fec5"
|
inputId="0030e56a57e74a4ab92de7fb8e97fec5"
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
validationRules="last-name-required" />
|
:validationRules="rules.lastName" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import addressQuestions from "@/iss-components/address-questions/address-questions";
|
import addressQuestions from '@/iss-components/address-questions/address-questions.vue';
|
||||||
import textboxQuestion from "@/digital-components/textbox-question/textbox-question";
|
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||||
import { defineRule } from "vee-validate";
|
import globalRules from '@/constants/global-rules';
|
||||||
import { required } from "@/helpers/validation-rules";
|
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
|
||||||
defineRule("first-name-required", required(errorMessages.FIRST_NAME_REQUIRED));
|
|
||||||
defineRule("last-name-required", required(errorMessages.LAST_NAME_REQUIRED));
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "customer-questions",
|
name: "customer-questions",
|
||||||
|
|
@ -56,6 +50,14 @@ export default {
|
||||||
},
|
},
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
},
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
rules: {
|
||||||
|
firstName: globalRules.FIRST_NAME_REQUIRED,
|
||||||
|
lastName: globalRules.LAST_NAME_REQUIRED
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
customerModel: {
|
customerModel: {
|
||||||
get: function () {
|
get: function () {
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||||
:questionsData="questionsData"
|
:questionsData="questionsData"
|
||||||
validationRules="questions-required"
|
:validationRules="rules.optionRequired"
|
||||||
v-model="selectedAnswers"
|
v-model="selectedAnswers"
|
||||||
@forwardButtonAction="forwardButtonAction"
|
@forwardButtonAction="forwardButtonAction"
|
||||||
@back-click="navigateBack"
|
@back-click="navigateBack"
|
||||||
|
|
@ -26,14 +26,11 @@ import { settleAllPromises } from '@/helpers/layout-helper';
|
||||||
// Import Component
|
// Import Component
|
||||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||||
import { issPageValues } from "@/router/router-constants/issPage-values";
|
import { issPageValues } from "@/router/router-constants/issPage-values";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
import { required } from "@/helpers/validation-rules";
|
|
||||||
import { useMainStore } from "@/store";
|
import { useMainStore } from "@/store";
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import globalRules from '@/constants/global-rules';
|
||||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||||
import questionsPageLayout from "@/iss-components/questions-page-layout/questions-page-layout.vue";
|
import questionsPageLayout from "@/iss-components/questions-page-layout/questions-page-layout.vue";
|
||||||
// DEFINE VALIDATION RULES
|
|
||||||
defineRule("questions-required", required(errorMessages.OPTION_REQUIRED));
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'capability-questions',
|
name: 'capability-questions',
|
||||||
|
|
@ -45,8 +42,11 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
questionsData: [],
|
questionsData: [],
|
||||||
selectedAnswers: {},
|
selectedAnswers: {},
|
||||||
currentGlassIndex: 0,
|
currentGlassIndex: 0,
|
||||||
|
rules: {
|
||||||
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
|
||||||
226
src/layouts/contact-details/contact-details.spec.js
Normal file
226
src/layouts/contact-details/contact-details.spec.js
Normal file
|
|
@ -0,0 +1,226 @@
|
||||||
|
// Components
|
||||||
|
import contactDetails from '@/layouts/contact-details/contact-details.vue';
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import { shallowMount } from '@vue/test-utils';
|
||||||
|
import { getMountOptions } from '@/helpers/unit-test-helper';
|
||||||
|
import { getRandomString, getRandomInt } from '@/helpers/data-generation';
|
||||||
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
|
import { navigationScenarios } from '@/router/router-constants/navigation-scenarios';
|
||||||
|
|
||||||
|
describe('contactDetails.vue', () => {
|
||||||
|
describe('Rendering', () => {
|
||||||
|
test('Should render site header', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const siteHeader = wrapper.findComponent({ ref: 'siteHeader' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(siteHeader.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render sub title', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const siteSubHeader = wrapper.findComponent({ ref: 'siteSubHeader' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(siteSubHeader.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render first name question subcomponent', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const firstNameQuestion = wrapper.findComponent({ ref: 'firstNameQuestion' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(firstNameQuestion.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render last name question subcomponent', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const lastNameQuestion = wrapper.findComponent({ ref: 'lastNameQuestion' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(lastNameQuestion.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render email question subcomponent', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const emailQuestion = wrapper.findComponent({ ref: 'emailQuestion' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(emailQuestion.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render phone number question subcomponent', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const phoneNumberQuestion = wrapper.findComponent({ ref: 'phoneNumberQuestion' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(phoneNumberQuestion.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render text updates checkbox subcomponent', () => {
|
||||||
|
// Arrange
|
||||||
|
const checkboxLabel = getRandomString(50, 100);
|
||||||
|
const mockMixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn().mockImplementation(() =>
|
||||||
|
checkboxLabel),
|
||||||
|
setCmsContent: jest.fn()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const mountOptions = getMountOptions();
|
||||||
|
mountOptions.mixins = [mockMixin];
|
||||||
|
const wrapper = shallowMount(contactDetails, mountOptions);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const textUpdatesCheckbox = wrapper.findComponent({ ref: 'requestTextUpdatesCheckbox' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(textUpdatesCheckbox.exists()).toBe(true);
|
||||||
|
expect(wrapper.vm.requestTextUpdatesCheckboxText).toBe(`${checkboxLabel}*`);
|
||||||
|
});
|
||||||
|
test('Should render technician notes textarea question subcomponent', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const notesQuestion = wrapper.findComponent({ ref: 'notesQuestion' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(notesQuestion.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render disclaimer text', () => {
|
||||||
|
// Arrange
|
||||||
|
const disclaimerText = getRandomString(50, 100);
|
||||||
|
const mockMixin = {
|
||||||
|
methods: {
|
||||||
|
getCmsContent: jest.fn().mockImplementation(() =>
|
||||||
|
disclaimerText),
|
||||||
|
setCmsContent: jest.fn()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const mountOptions = getMountOptions();
|
||||||
|
mountOptions.mixins = [mockMixin];
|
||||||
|
const wrapper = shallowMount(contactDetails, mountOptions);
|
||||||
|
const expectedDisclaimerText = `*${disclaimerText} I also agree to Safelite's`;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const componentText = wrapper.text();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.textUpdateDisclaimerText).toBe(`*${disclaimerText}`);
|
||||||
|
expect(componentText).toContain(expectedDisclaimerText);
|
||||||
|
});
|
||||||
|
test('Should render privacy policy link', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const privacyPolicyLink = wrapper.findComponent({ ref: 'privacyPolicyLink' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(privacyPolicyLink.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render terms of use link', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const termsOfUseLink = wrapper.findComponent({ ref: 'termsOfUseLink' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(termsOfUseLink.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Should render site footer', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
const footer = wrapper.findComponent({ ref: 'siteFooter' });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(footer.exists()).toBe(true);
|
||||||
|
});
|
||||||
|
test('Mocked store yields expected data', () => {
|
||||||
|
// Arrange
|
||||||
|
const mountOptions = getMountOptions();
|
||||||
|
|
||||||
|
const firstName = getRandomString(4, 15);
|
||||||
|
const lastName = getRandomString(4, 15);
|
||||||
|
const emailAddress = getRandomString(10, 20);
|
||||||
|
const phoneNumber = getRandomInt(1000000000, 9999999999);
|
||||||
|
const mainInitialState = {
|
||||||
|
order: {
|
||||||
|
customer: {
|
||||||
|
firstName,
|
||||||
|
lastName,
|
||||||
|
emailAddress,
|
||||||
|
phoneNumber
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
mountOptions.global = {
|
||||||
|
plugins: [createTestingPinia({
|
||||||
|
initialState: {
|
||||||
|
main: mainInitialState
|
||||||
|
}
|
||||||
|
})]
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallowMount(contactDetails, mountOptions);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.firstName).toBe(firstName);
|
||||||
|
expect(wrapper.vm.lastName).toBe(lastName);
|
||||||
|
expect(wrapper.vm.email).toBe(emailAddress);
|
||||||
|
expect(wrapper.vm.phoneNumber).toBe(phoneNumber);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('Navigation', () => {
|
||||||
|
test('Back button clicked triggers navigation', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions({
|
||||||
|
router: {
|
||||||
|
navigate: jest.fn()
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.backButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.$router.navigate)
|
||||||
|
.toHaveBeenCalledWith(navigationScenarios.CLICKED_BACK, undefined);
|
||||||
|
});
|
||||||
|
test('Forward button clicked triggers navigation', () => {
|
||||||
|
// Arrange
|
||||||
|
const wrapper = shallowMount(contactDetails, getMountOptions({
|
||||||
|
router: {
|
||||||
|
navigate: jest.fn()
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Act
|
||||||
|
wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.$router.navigate)
|
||||||
|
.toHaveBeenCalledWith(navigationScenarios.CLICKED_FORWARD, undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,17 +1,96 @@
|
||||||
<template>
|
<template>
|
||||||
<Form @submit="onSubmit" @invalid-submit="onInvalidSubmit" ref="theForm" v-slot="{ meta }" >
|
<Form
|
||||||
|
ref="contact-details-form"
|
||||||
|
v-slot="{ meta }"
|
||||||
|
@submit="onSubmit"
|
||||||
|
@invalidSubmit="onInvalidSubmit">
|
||||||
<div class="page-container-grouped-styles">
|
<div class="page-container-grouped-styles">
|
||||||
<div class="fade-on-route-transition position-relative">
|
<div class="fade-on-route-transition position-relative">
|
||||||
<siteHeader cmsWidgetName="SiteHeaderWidget"/>
|
<siteHeader
|
||||||
|
ref="siteHeader"
|
||||||
|
:cmsWidgetName="widget.siteHeader" />
|
||||||
<div class="container-fluid pb-2">
|
<div class="container-fluid pb-2">
|
||||||
<p>Placeholder for contact details page</p>
|
<siteSubHeader
|
||||||
|
id="sub-header"
|
||||||
|
ref="siteSubHeader"
|
||||||
|
class="margin-top-16"
|
||||||
|
:cmsWidgetName="widget.siteSubHeader" />
|
||||||
|
<textboxQuestion
|
||||||
|
ref="firstNameQuestion"
|
||||||
|
v-model="firstName"
|
||||||
|
class="margin-top-24"
|
||||||
|
inputId="firstName"
|
||||||
|
:cmsWidgetName="widget.firstNameQuestion"
|
||||||
|
isRequired
|
||||||
|
:validationRules="rules.firstName" />
|
||||||
|
<textboxQuestion
|
||||||
|
ref="lastNameQuestion"
|
||||||
|
v-model="lastName"
|
||||||
|
class="margin-top-16"
|
||||||
|
inputId="lastName"
|
||||||
|
:cmsWidgetName="widget.lastNameQuestion"
|
||||||
|
isRequired
|
||||||
|
:validationRules="rules.lastName" />
|
||||||
|
<textboxQuestion
|
||||||
|
ref="emailQuestion"
|
||||||
|
v-model="email"
|
||||||
|
class="margin-top-16"
|
||||||
|
inputId="email"
|
||||||
|
:cmsWidgetName="widget.emailQuestion"
|
||||||
|
isRequired
|
||||||
|
:validationRules="rules.email" />
|
||||||
|
<textboxQuestion
|
||||||
|
ref="phoneNumberQuestion"
|
||||||
|
v-model="phoneNumber"
|
||||||
|
class="margin-top-16"
|
||||||
|
inputId="phoneNumber"
|
||||||
|
:cmsWidgetName="widget.phoneNumberQuestion"
|
||||||
|
isRequired
|
||||||
|
:validationRules="rules.phoneNumber" />
|
||||||
|
<checkbox
|
||||||
|
ref="requestTextUpdatesCheckbox"
|
||||||
|
v-model="requestTextUpdates"
|
||||||
|
class="margin-top-8"
|
||||||
|
checkboxName="requestTextUpdates"
|
||||||
|
buttonID="requestTextUpdates"
|
||||||
|
:checkboxLabel="requestTextUpdatesCheckboxText" />
|
||||||
|
|
||||||
|
<textareaQuestion
|
||||||
|
ref="notesQuestion"
|
||||||
|
v-model="notesForTechnician"
|
||||||
|
class="margin-top-16"
|
||||||
|
inputId="technicianNotes"
|
||||||
|
:isDisabled="false"
|
||||||
|
:isRequired="false"
|
||||||
|
:cmsWidgetName="widget.notesQuestion"
|
||||||
|
maxLength="500"
|
||||||
|
:inputRows="3" />
|
||||||
|
|
||||||
|
<p
|
||||||
|
ref="disclaimerText"
|
||||||
|
class="disclaimer margin-top-24">
|
||||||
|
{{ textUpdateDisclaimerText }} I also agree to Safelite's
|
||||||
|
<textLink
|
||||||
|
ref="privacyPolicyLink"
|
||||||
|
class="disclaimer-link"
|
||||||
|
linkType="text"
|
||||||
|
text="Privacy Policy"
|
||||||
|
href="//www.safelite.com/privacy-center" />
|
||||||
|
and
|
||||||
|
<textLink
|
||||||
|
ref="termsOfUseLink"
|
||||||
|
class="disclaimer-link"
|
||||||
|
linkType="text"
|
||||||
|
text="Terms of Use"
|
||||||
|
href="//www.safelite.com/terms-of-use" />.
|
||||||
|
</p>
|
||||||
|
|
||||||
<siteFooter
|
<siteFooter
|
||||||
cmsWidgetName="SiteFooterWidget"
|
ref="siteFooter"
|
||||||
ref="siteFooter"
|
:cmsWidgetName="widget.siteFooter"
|
||||||
:isForwardActionDisabled="!meta.valid"
|
:isForwardActionDisabled="!meta.valid"
|
||||||
@ForwardClicked="navigateForward"
|
@forwardClicked="navigateForward"
|
||||||
@back-clicked="backButtonAction"
|
@backClicked="backButtonAction" />
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -19,67 +98,131 @@
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
// Components
|
// Components
|
||||||
import siteHeader from '@/iss-components/site-header/site-header';
|
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||||
import siteFooter from "@/iss-components/site-footer/site-footer";
|
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||||
|
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||||
|
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||||
|
import checkbox from '@/ux-components/checkbox/checkbox.vue';
|
||||||
|
import textareaQuestion from '@/digital-components/textarea-question/textarea-question.vue';
|
||||||
|
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||||
|
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { Form } from 'vee-validate';
|
||||||
import { Form } from "vee-validate";
|
import BaseFormMixin from '@/mixins/base-form-mixin';
|
||||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
|
import globalRules from '@/constants/global-rules';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "contact-details",
|
name: 'contact-details',
|
||||||
|
components: {
|
||||||
|
siteHeader,
|
||||||
|
siteSubHeader,
|
||||||
|
textboxQuestion,
|
||||||
|
checkbox,
|
||||||
|
textareaQuestion,
|
||||||
|
siteFooter,
|
||||||
|
// eslint-disable-next-line vue/no-reserved-component-names
|
||||||
|
Form,
|
||||||
|
textLink
|
||||||
|
},
|
||||||
mixins: [BaseFormMixin],
|
mixins: [BaseFormMixin],
|
||||||
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
const cmsContent = await fetchCmsContentForPage(to.query.issPage);
|
||||||
|
|
||||||
|
next((vm) => {
|
||||||
|
vm.setCmsContent(cmsContent);
|
||||||
|
});
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
|
return {
|
||||||
|
firstName: useMainStore().order.customer.firstName,
|
||||||
|
lastName: useMainStore().order.customer.lastName,
|
||||||
|
email: useMainStore().order.customer.emailAddress,
|
||||||
|
phoneNumber: useMainStore().order.customer.phoneNumber,
|
||||||
|
requestTextUpdates: false,
|
||||||
|
notesForTechnician: '',
|
||||||
|
widget: {
|
||||||
|
siteHeader: 'SiteHeaderWidget',
|
||||||
|
siteSubHeader: 'SiteSubHeaderWidget',
|
||||||
|
firstNameQuestion: 'FirstNameQuestionWidget',
|
||||||
|
lastNameQuestion: 'LastNameQuestionWidget',
|
||||||
|
emailQuestion: 'EmailQuestionWidget',
|
||||||
|
phoneNumberQuestion: 'PhoneNumberQuestionWidget',
|
||||||
|
requestTextUpdates: 'TextContentWidget',
|
||||||
|
notesQuestion: 'NotesQuestionWidget',
|
||||||
|
disclaimer: 'TextUpdateDisclaimerWidget',
|
||||||
|
siteFooter: 'SiteFooterWidget'
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
firstName: globalRules.FIRST_NAME_REQUIRED,
|
||||||
|
lastName: globalRules.LAST_NAME_REQUIRED,
|
||||||
|
email: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
|
||||||
|
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`
|
||||||
|
}
|
||||||
|
};
|
||||||
},
|
},
|
||||||
setup() {
|
computed: {
|
||||||
const mainStore = useMainStore();
|
/**
|
||||||
return { mainStore };
|
* @summary Returns the CMS text associated with the "get text updates" checkbox.
|
||||||
|
*/
|
||||||
|
requestTextUpdatesCheckboxText() {
|
||||||
|
return `${this.getCmsContent(this.widget.requestTextUpdates, 'Text')}*`;
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* @summary Returns the CMS text associated with the "get text updates" checkbox.
|
||||||
|
*/
|
||||||
|
textUpdateDisclaimerText() {
|
||||||
|
return `*${this.getCmsContent(this.widget.disclaimer, 'Text')}`;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
async beforeRouteEnter(to, from, next)
|
methods:
|
||||||
{
|
{
|
||||||
// Call APIs
|
/**
|
||||||
const cmsContentPromise = fetchCmsContentForPage(to.query.issPage);
|
* @summary Steps to perform when back button clicked.
|
||||||
|
*/
|
||||||
// Settle promises and get results
|
backButtonAction() {
|
||||||
const promiseResultMap = [
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
{
|
|
||||||
resultKey: "cmsContent",
|
|
||||||
promise: cmsContentPromise,
|
|
||||||
},];
|
|
||||||
|
|
||||||
//use resultMap to populate layout content.
|
|
||||||
let resultMap = await settleAllPromises(promiseResultMap);
|
|
||||||
|
|
||||||
next((vm) => {
|
|
||||||
vm.setCmsContent(resultMap.cmsContent);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
methods:
|
|
||||||
{
|
|
||||||
backButtonAction() {
|
|
||||||
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
|
||||||
},
|
|
||||||
|
|
||||||
forwardButtonAction() {
|
|
||||||
},
|
|
||||||
|
|
||||||
navigateForward() {
|
|
||||||
this.$router.navigate(
|
|
||||||
this.navigationScenarios.CLICKED_FORWARD,
|
|
||||||
this.$route
|
|
||||||
);
|
|
||||||
},
|
|
||||||
},
|
|
||||||
components: {
|
|
||||||
siteHeader,
|
|
||||||
siteFooter,
|
|
||||||
Form,
|
|
||||||
},
|
},
|
||||||
|
/**
|
||||||
|
* @summary Steps to perform when forward button clicked.
|
||||||
|
*/
|
||||||
|
forwardButtonAction() {
|
||||||
|
this.$router.navigate(this.navigationScenarios.CLICKED_FORWARD,
|
||||||
|
this.$route);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
#sub-header {
|
||||||
|
span {
|
||||||
|
color: $black;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-top-24 {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-top-16 {
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.margin-top-8 {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disclaimer {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $darker-gray;
|
||||||
|
font-weight: 400;
|
||||||
|
}
|
||||||
|
|
||||||
|
.disclaimer-link {
|
||||||
|
text-decoration: none;
|
||||||
|
line-height: normal;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@
|
||||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||||
:questionsData="questionsData"
|
:questionsData="questionsData"
|
||||||
validationRules="questions-required"
|
:validationRules="rules.optionRequired"
|
||||||
v-model="selectedAnswers"
|
v-model="selectedAnswers"
|
||||||
@forwardButtonAction="forwardButtonAction"
|
@forwardButtonAction="forwardButtonAction"
|
||||||
@back-click="navigateBack"
|
@back-click="navigateBack"
|
||||||
|
|
@ -25,9 +25,7 @@
|
||||||
// Import Supporting Files
|
// Import Supporting Files
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { defineRule } from "vee-validate";
|
import globalRules from '@/constants/global-rules';
|
||||||
import { required } from "@/helpers/validation-rules";
|
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
|
||||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||||
import { useMainStore } from "@/store";
|
import { useMainStore } from "@/store";
|
||||||
import { issPageValues } from "@/router/router-constants/issPage-values";
|
import { issPageValues } from "@/router/router-constants/issPage-values";
|
||||||
|
|
@ -37,9 +35,6 @@ import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
import { Form } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
import questionsPageLayout from "@/iss-components/questions-page-layout/questions-page-layout.vue";
|
import questionsPageLayout from "@/iss-components/questions-page-layout/questions-page-layout.vue";
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
|
||||||
defineRule("questions-required", required(errorMessages.OPTION_REQUIRED));
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "molding-questions",
|
name: "molding-questions",
|
||||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||||
|
|
@ -65,6 +60,9 @@ export default {
|
||||||
questionsData: [],
|
questionsData: [],
|
||||||
selectedAnswers: {},
|
selectedAnswers: {},
|
||||||
currentGlassIndex: 0,
|
currentGlassIndex: 0,
|
||||||
|
rules: {
|
||||||
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
:alertFewMoreQuestionsHeader="AlertFewMoreQuestionsHeader"
|
||||||
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
:alertFewMoreQuestionsCopy="AlertFewMoreQuestionsCopy"
|
||||||
:questionsData="questionsData"
|
:questionsData="questionsData"
|
||||||
validationRules="questions-required"
|
:validationRules="rules.optionRequired"
|
||||||
v-model="selectedAnswers"
|
v-model="selectedAnswers"
|
||||||
@forwardButtonAction="forwardButtonAction"
|
@forwardButtonAction="forwardButtonAction"
|
||||||
@back-click="navigateBack"
|
@back-click="navigateBack"
|
||||||
|
|
@ -23,14 +23,10 @@ import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import { issPageValues } from "@/router/router-constants/issPage-values";
|
import { issPageValues } from "@/router/router-constants/issPage-values";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
import { required } from "@/helpers/validation-rules";
|
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
|
||||||
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
import vehicleQuestionsMixin from "@/mixins/vehicle-questions-mixin";
|
||||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
|
import globalRules from '@/constants/global-rules';
|
||||||
// DEFINE VALIDATION RULES
|
|
||||||
defineRule("questions-required", required(errorMessages.OPTION_REQUIRED));
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "part-questions",
|
name: "part-questions",
|
||||||
|
|
@ -59,6 +55,9 @@ export default {
|
||||||
questionsData: [],
|
questionsData: [],
|
||||||
selectedAnswers: {},
|
selectedAnswers: {},
|
||||||
currentGlassIndex: 0,
|
currentGlassIndex: 0,
|
||||||
|
rules: {
|
||||||
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
isRequired
|
isRequired
|
||||||
ref="policyHolderFirstName"
|
ref="policyHolderFirstName"
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
validationRules="first-name-required" />
|
:validationRules="rules.firstName" />
|
||||||
<textboxQuestion
|
<textboxQuestion
|
||||||
class="mt-4"
|
class="mt-4"
|
||||||
inputId="lastNameField"
|
inputId="lastNameField"
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
isRequired
|
isRequired
|
||||||
ref="policyHolderLastName"
|
ref="policyHolderLastName"
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
validationRules="last-name-required" />
|
:validationRules="rules.lastName" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<siteFooter
|
<siteFooter
|
||||||
|
|
@ -51,16 +51,11 @@ import siteFooter from "@/iss-components/site-footer/site-footer";
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
import { required } from "@/helpers/validation-rules";
|
import globalRules from '@/constants/global-rules';
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
|
||||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
|
|
||||||
//define validation rules
|
|
||||||
defineRule("first-name-required", required(errorMessages.POLICYHOLDER_FIRST_NAME_REQUIRED));
|
|
||||||
defineRule("last-name-required", required(errorMessages.POLICYHOLDER_LAST_NAME_REQUIRED));
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "policy-holder-details",
|
name: "policy-holder-details",
|
||||||
mixins: [BaseFormMixin],
|
mixins: [BaseFormMixin],
|
||||||
|
|
@ -68,6 +63,10 @@ export default {
|
||||||
return {
|
return {
|
||||||
customerQuestions: this.getPolicyHolderDetailsFromStore(),
|
customerQuestions: this.getPolicyHolderDetailsFromStore(),
|
||||||
vehiclesFound: [],
|
vehiclesFound: [],
|
||||||
|
rules: {
|
||||||
|
firstName: globalRules.POLICYHOLDER_FIRST_NAME_REQUIRED,
|
||||||
|
lastName: globalRules.POLICYHOLDER_LAST_NAME_REQUIRED
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
class="px-4"
|
class="px-4"
|
||||||
cmsWidgetName="PolicyVehiclesQuestion"
|
cmsWidgetName="PolicyVehiclesQuestion"
|
||||||
:vehicles="VehiclesForQuestions"
|
:vehicles="VehiclesForQuestions"
|
||||||
validationRules="option-required"
|
:validationRules="rules.optionRequired"
|
||||||
v-model="selectedVehicleVin"
|
v-model="selectedVehicleVin"
|
||||||
/>
|
/>
|
||||||
<siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter" :isForwardActionDisabled="!meta.valid" @ForwardClicked="forwardButtonAction" @back-clicked="backButtonAction"/>
|
<siteFooter cmsWidgetName="SiteFooterWidget" ref="siteFooter" :isForwardActionDisabled="!meta.valid" @ForwardClicked="forwardButtonAction" @back-clicked="backButtonAction"/>
|
||||||
|
|
@ -35,17 +35,14 @@ import policyVehiclesQuestion from "@/layouts/policy-vehicles/policy-vehicles-qu
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { required } from "@/helpers/validation-rules";
|
import { Form } from "vee-validate";
|
||||||
import { Form, defineRule } from "vee-validate";
|
|
||||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
import { issPageValues } from "@/router/router-constants/issPage-values";
|
import { issPageValues } from "@/router/router-constants/issPage-values";
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import globalRules from '@/constants/global-rules';
|
||||||
import { vehicleSelectionOptions } from "@/constants/vehicle-selection-options";
|
import { vehicleSelectionOptions } from "@/constants/vehicle-selection-options";
|
||||||
import { endorsementOptions } from "@/constants/endorsement-options";
|
import { endorsementOptions } from "@/constants/endorsement-options";
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
|
||||||
defineRule("option-required", required(errorMessages.OPTION_REQUIRED));
|
|
||||||
export default {
|
export default {
|
||||||
name: "policy-vehicles",
|
name: "policy-vehicles",
|
||||||
mixins: [BaseFormMixin],
|
mixins: [BaseFormMixin],
|
||||||
|
|
@ -57,7 +54,10 @@ export default {
|
||||||
? policyVehicles[0].vin
|
? policyVehicles[0].vin
|
||||||
: "",
|
: "",
|
||||||
displayGeneric: true,
|
displayGeneric: true,
|
||||||
bailout: false
|
bailout: false,
|
||||||
|
rules: {
|
||||||
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async beforeRouteEnter(to, from, next)
|
async beforeRouteEnter(to, from, next)
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
groupName="prefQuestions"
|
groupName="prefQuestions"
|
||||||
buttonTypeString="providerPrefRadio"
|
buttonTypeString="providerPrefRadio"
|
||||||
v-model="selectedProvider"
|
v-model="selectedProvider"
|
||||||
validationRules="option-required"
|
:validationRules="rules.optionRequired"
|
||||||
isRequired
|
isRequired
|
||||||
class="mx-5" />
|
class="mx-5" />
|
||||||
<div class="px-5">
|
<div class="px-5">
|
||||||
|
|
@ -44,7 +44,6 @@
|
||||||
// Import Supporting Files
|
// Import Supporting Files
|
||||||
import { fetchCmsContentForPage, setupModalLinks, processIfStatements } from '@/helpers/cms-content-helper';
|
import { fetchCmsContentForPage, setupModalLinks, processIfStatements } from '@/helpers/cms-content-helper';
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
import { required } from "@/helpers/validation-rules";
|
|
||||||
import { errorMessages } from "@/constants/error-messages";
|
import { errorMessages } from "@/constants/error-messages";
|
||||||
import buttonQuestion from "@/digital-components/button-question/button-question";
|
import buttonQuestion from "@/digital-components/button-question/button-question";
|
||||||
import contentGroupModal from "@/iss-components/content-group-modal/content-group-modal";
|
import contentGroupModal from "@/iss-components/content-group-modal/content-group-modal";
|
||||||
|
|
@ -52,7 +51,7 @@ import { issPageValues } from "@/router/router-constants/issPage-values";
|
||||||
|
|
||||||
// Import Component
|
// Import Component
|
||||||
import baseFormMixin from "@/mixins/base-form-mixin";
|
import baseFormMixin from "@/mixins/base-form-mixin";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form } from "vee-validate";
|
||||||
import siteFooter from "@/iss-components/site-footer/site-footer";
|
import siteFooter from "@/iss-components/site-footer/site-footer";
|
||||||
import siteHeader from "@/iss-components/site-header/site-header";
|
import siteHeader from "@/iss-components/site-header/site-header";
|
||||||
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header";
|
import siteSubHeader from "@/iss-components/site-sub-header/site-sub-header";
|
||||||
|
|
@ -61,9 +60,8 @@ import recalModal from "@/layouts/coverage-statement/recal-modal/recal-modal";
|
||||||
import steeringModal from "@/layouts/provider-preference/steering-modal/steering-modal";
|
import steeringModal from "@/layouts/provider-preference/steering-modal/steering-modal";
|
||||||
import shopPreferenceModal from "@/layouts/provider-preference/shop-preference-modal/shop-preference-modal";
|
import shopPreferenceModal from "@/layouts/provider-preference/shop-preference-modal/shop-preference-modal";
|
||||||
import tpaRecalModal from "@/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue"
|
import tpaRecalModal from "@/layouts/provider-preference/tpa-recal-modal/tpa-recal-modal.vue"
|
||||||
|
import globalRules from '@/constants/global-rules';
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
|
||||||
defineRule('option-required', required(errorMessages.OPTION_REQUIRED));
|
|
||||||
const options = { SAFELITE: 'SafeliteOption', TPA: 'TPAOption' };
|
const options = { SAFELITE: 'SafeliteOption', TPA: 'TPAOption' };
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -88,6 +86,9 @@ export default {
|
||||||
selectedProvider : null,
|
selectedProvider : null,
|
||||||
showSteeringLink: false,
|
showSteeringLink: false,
|
||||||
tpaAcknowledgement: false,
|
tpaAcknowledgement: false,
|
||||||
|
rules: {
|
||||||
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
async beforeRouteEnter(to, from, next) {
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
<checkBox
|
<checkBox
|
||||||
class="mb-2"
|
class="mb-2"
|
||||||
:class="showError && ' has-error'"
|
:class="showError && ' has-error'"
|
||||||
validationRules="option-required"
|
:validationRules="rules.optionRequired"
|
||||||
checkboxName="tpaAcknowledgement"
|
checkboxName="tpaAcknowledgement"
|
||||||
buttonID="tpaAcknowledgement"
|
buttonID="tpaAcknowledgement"
|
||||||
:tabIndex="0"
|
:tabIndex="0"
|
||||||
|
|
@ -35,6 +35,7 @@
|
||||||
import modal from "@/digital-components/modal/modal";
|
import modal from "@/digital-components/modal/modal";
|
||||||
import tpaRecalToggle from "@/layouts/provider-preference/tpa-recal-modal/tpa-recal-toggle/tpa-recal-toggle.vue"
|
import tpaRecalToggle from "@/layouts/provider-preference/tpa-recal-modal/tpa-recal-toggle/tpa-recal-toggle.vue"
|
||||||
import checkBox from "@/ux-components/checkbox/checkbox.vue"
|
import checkBox from "@/ux-components/checkbox/checkbox.vue"
|
||||||
|
import globalRules from "@/constants/global-rules";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "content-group-modal",
|
name: "content-group-modal",
|
||||||
|
|
@ -45,7 +46,10 @@ export default {
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
acknowledged: false,
|
acknowledged: false,
|
||||||
showError: false
|
showError: false,
|
||||||
|
rules: {
|
||||||
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
emits: ["buttonClick"],
|
emits: ["buttonClick"],
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
:availableLineItems="availableLineItems"
|
:availableLineItems="availableLineItems"
|
||||||
@vapsItemsSelected="vapsItemsSelectedAction"
|
@vapsItemsSelected="vapsItemsSelectedAction"
|
||||||
v-on:link-event="openModalAction"
|
v-on:link-event="openModalAction"
|
||||||
validationRules="option-required"
|
:validationRules="rules.optionRequired"
|
||||||
isRequired
|
isRequired
|
||||||
/>
|
/>
|
||||||
<p class="caption disclaimer" v-html="PriceDisclaimerText"></p>
|
<p class="caption disclaimer" v-html="PriceDisclaimerText"></p>
|
||||||
|
|
@ -52,8 +52,7 @@ import { required } from '@/helpers/validation-rules';
|
||||||
import { errorMessages } from '@/constants/error-messages';
|
import { errorMessages } from '@/constants/error-messages';
|
||||||
import { Form, defineRule } from 'vee-validate';
|
import { Form, defineRule } from 'vee-validate';
|
||||||
import { allGlassPartsAndItemsHavePrices } from '@/layouts/service-packages/service-package-helper/service-package-helper'
|
import { allGlassPartsAndItemsHavePrices } from '@/layouts/service-packages/service-package-helper/service-package-helper'
|
||||||
|
import globalRules from "@/constants/global-rules";
|
||||||
defineRule('option-required', required(errorMessages.OPTION_REQUIRED));
|
|
||||||
|
|
||||||
const store = useMainStore();
|
const store = useMainStore();
|
||||||
|
|
||||||
|
|
@ -112,7 +111,10 @@ export default {
|
||||||
selectedVaps: [],
|
selectedVaps: [],
|
||||||
availableLineItems: [],
|
availableLineItems: [],
|
||||||
supportingItems: [],
|
supportingItems: [],
|
||||||
pricedGlassParts: []
|
pricedGlassParts: [],
|
||||||
|
rules: {
|
||||||
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,10 @@ import {vinLookupMethodSelections} from '@/constants/vin-lookup-methods';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import { createTestingPinia } from '@pinia/testing';
|
import { createTestingPinia } from '@pinia/testing';
|
||||||
import { mapStores } from "pinia";
|
import { mapStores } from "pinia";
|
||||||
|
import { defineRule } from 'vee-validate';
|
||||||
|
import { errorMessages } from '@/constants/error-messages';
|
||||||
|
import globalRules from '@/constants/global-rules';
|
||||||
|
import { required } from '@/helpers/validation-rules';
|
||||||
|
|
||||||
const pinia = createTestingPinia();
|
const pinia = createTestingPinia();
|
||||||
useMainStore(pinia);
|
useMainStore(pinia);
|
||||||
|
|
@ -44,6 +48,7 @@ const siteFooterWidgetMockData = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function setupMocks() {
|
function setupMocks() {
|
||||||
|
defineRule(globalRules.OPTION_REQUIRED, required(errorMessages.OPTION_REQUIRED));
|
||||||
const mockRoute = {
|
const mockRoute = {
|
||||||
query: {
|
query: {
|
||||||
issPage: 'vehicle-lookup',
|
issPage: 'vehicle-lookup',
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
button-type-string="listButton"
|
button-type-string="listButton"
|
||||||
:question-text="questionTextFromCms"
|
:question-text="questionTextFromCms"
|
||||||
is-required
|
is-required
|
||||||
validation-rules="option-required"
|
:validation-rules="rules.optionRequired"
|
||||||
data-test-id="vin-lookup-methods-button-question"
|
data-test-id="vin-lookup-methods-button-question"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -13,32 +13,30 @@
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
// Import Other Supporting Files
|
// Import Other Supporting Files
|
||||||
import { defineRule } from 'vee-validate';
|
|
||||||
import { required } from '@/helpers/validation-rules';
|
|
||||||
import { errorMessages } from '@/constants/error-messages';
|
|
||||||
import { useMainStore } from "@/store";
|
import { useMainStore } from "@/store";
|
||||||
import {vinLookupMethodSelections} from '@/constants/vin-lookup-methods';
|
import { vinLookupMethodSelections } from '@/constants/vin-lookup-methods';
|
||||||
import { settleAllPromises } from "@/helpers/layout-helper";
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import globalRules from '@/constants/global-rules';
|
||||||
|
|
||||||
// Import Component
|
// Import Component
|
||||||
import ButtonQuestion from '@/digital-components/button-question/button-question.vue';
|
import ButtonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||||
|
|
||||||
// Define Validation Rules
|
|
||||||
defineRule('option-required', required(errorMessages.OPTION_REQUIRED));
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'vin-lookup-methods',
|
name: 'vin-lookup-methods',
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
questionTextFromCms: '',
|
questionTextFromCms: '',
|
||||||
answersFromCms: [],
|
answersFromCms: [],
|
||||||
|
rules: {
|
||||||
|
optionRequired: globalRules.OPTION_REQUIRED
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
modelValue: String,
|
modelValue: String,
|
||||||
cmsWidgetName: {
|
cmsWidgetName: {
|
||||||
type: String,
|
type: String,
|
||||||
required,
|
required: true
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
ref="policyNumber"
|
ref="policyNumber"
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
:isDisabled="isPolicyHolderEnabled"
|
:isDisabled="isPolicyHolderEnabled"
|
||||||
validationRules="policy-number-required" />
|
:validationRules="rules.policyNumber" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-4" v-if="this.isCoverageEnabled">
|
<div class="row mt-4" v-if="this.isCoverageEnabled">
|
||||||
|
|
@ -26,7 +26,7 @@
|
||||||
v-model="welcomePageModel.policyZipCode"
|
v-model="welcomePageModel.policyZipCode"
|
||||||
isRequired
|
isRequired
|
||||||
ref="policyZip"
|
ref="policyZip"
|
||||||
validationRules="policy-zip-required|policy-zip-format" />
|
:validationRules="rules.policyZip" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mt-4">
|
<div class="row mt-4">
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
:max="new Date().toJSON().slice(0,10)"
|
:max="new Date().toJSON().slice(0,10)"
|
||||||
:min="'1972-12-01'"
|
:min="'1972-12-01'"
|
||||||
validationRules="loss-date-required"
|
:validationRules="rules.lossDate"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
inputId="damageCauseQuestionField"
|
inputId="damageCauseQuestionField"
|
||||||
:options="DamageCauseOptions"
|
:options="DamageCauseOptions"
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
validationRules="damage-option-required"
|
:validationRules="rules.damageOption"
|
||||||
placeHolderText="Select an option"
|
placeHolderText="Select an option"
|
||||||
id="welcomeDropdown"
|
id="welcomeDropdown"
|
||||||
/>
|
/>
|
||||||
|
|
@ -71,7 +71,7 @@
|
||||||
inputId="phoneNumberField"
|
inputId="phoneNumberField"
|
||||||
cmsWidgetName="PhoneNumberQuestion"
|
cmsWidgetName="PhoneNumberQuestion"
|
||||||
v-model="welcomePageModel.phoneNumber"
|
v-model="welcomePageModel.phoneNumber"
|
||||||
validationRules="phone-number-required|phone-number-format"
|
:validationRules="rules.phoneNumber"
|
||||||
isRequired
|
isRequired
|
||||||
ref="phoneNumber"
|
ref="phoneNumber"
|
||||||
mask="###-###-####"
|
mask="###-###-####"
|
||||||
|
|
@ -85,7 +85,7 @@
|
||||||
cmsWidgetName="EmailAddressQuestion"
|
cmsWidgetName="EmailAddressQuestion"
|
||||||
v-model="welcomePageModel.email"
|
v-model="welcomePageModel.email"
|
||||||
ref="email"
|
ref="email"
|
||||||
validationRules="email-address-required|email-address-format"
|
:validationRules="rules.email"
|
||||||
isRequired
|
isRequired
|
||||||
disableAutoFill />
|
disableAutoFill />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -101,7 +101,7 @@
|
||||||
ref="damageCity"
|
ref="damageCity"
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
v-if="this.displayDamageCityQuestion"
|
v-if="this.displayDamageCityQuestion"
|
||||||
validationRules="loss-city-required" />
|
:validationRules="rules.lossCity" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
@ -113,7 +113,7 @@
|
||||||
ref="state"
|
ref="state"
|
||||||
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
inputId="8fdf9dc2e13e430eb57529499dceb3eb"
|
||||||
:options="getStates"
|
:options="getStates"
|
||||||
validationRules="loss-state-required"
|
:validationRules="rules.lossState"
|
||||||
isRequired
|
isRequired
|
||||||
disableAutoFill
|
disableAutoFill
|
||||||
v-if="this.displayDamageStateQuestion"
|
v-if="this.displayDamageStateQuestion"
|
||||||
|
|
@ -127,11 +127,11 @@
|
||||||
class="px-0 mt-4"
|
class="px-0 mt-4"
|
||||||
cmsWidgetName="GlassOnlyQuestion"
|
cmsWidgetName="GlassOnlyQuestion"
|
||||||
v-model="welcomePageModel.isDamageGlassOnly"
|
v-model="welcomePageModel.isDamageGlassOnly"
|
||||||
inputId = "isDamageGlassOnly"
|
inputId="isDamageGlassOnly"
|
||||||
:answers="DamageGlassOnlyOptions"
|
:answers="DamageGlassOnlyOptions"
|
||||||
:questionText="DamageGlassOnlyQuestion"
|
:questionText="DamageGlassOnlyQuestion"
|
||||||
buttonTypeString="listButtonHorizontal"
|
buttonTypeString="listButtonHorizontal"
|
||||||
validationRules="damage-option-required"
|
:validationRules="rules.damageOption"
|
||||||
isRequired
|
isRequired
|
||||||
isSmallQuestionLabelText
|
isSmallQuestionLabelText
|
||||||
ref="glassOnlyDamage"
|
ref="glassOnlyDamage"
|
||||||
|
|
@ -173,32 +173,17 @@
|
||||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import { states } from "@/constants/states"
|
import { states } from "@/constants/states"
|
||||||
|
import globalRules from '@/constants/global-rules';
|
||||||
|
|
||||||
//define validation rules
|
//define validation rules
|
||||||
defineRule("loss-date-required", required(errorMessages.LOSS_DATE_REQUIRED));
|
defineRule("loss-date-required", required(errorMessages.LOSS_DATE_REQUIRED));
|
||||||
defineRule("loss-cause-required", required(errorMessages.LOSS_CAUSE_REQUIRED));
|
|
||||||
defineRule("policy-number-required", required(errorMessages.POLICY_NUMBER_REQUIRED));
|
defineRule("policy-number-required", required(errorMessages.POLICY_NUMBER_REQUIRED));
|
||||||
defineRule("loss-date-required", required(errorMessages.LOSS_DATE_REQUIRED));
|
|
||||||
defineRule("loss-state-required", required(errorMessages.LOSS_STATE_REQUIRED));
|
defineRule("loss-state-required", required(errorMessages.LOSS_STATE_REQUIRED));
|
||||||
defineRule("loss-city-required", required(errorMessages.LOSS_CITY_REQUIRED));
|
defineRule("loss-city-required", required(errorMessages.LOSS_CITY_REQUIRED));
|
||||||
defineRule("phone-number-required", required(errorMessages.PHONE_NUMBER_FORMAT));
|
|
||||||
defineRule("email-address-required", required(errorMessages.EMAIL_ADDRESS_REQUIRED));
|
|
||||||
defineRule("damage-option-required", required(errorMessages.DAMAGE_OPTION_REQUIRED));
|
defineRule("damage-option-required", required(errorMessages.DAMAGE_OPTION_REQUIRED));
|
||||||
defineRule("policy-zip-required", required(errorMessages.POLICY_ZIP_REQUIRED));
|
defineRule("policy-zip-required", required(errorMessages.POLICY_ZIP_REQUIRED));
|
||||||
defineRule("policy-zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.POLICY_ZIP_FORMAT));
|
defineRule("policy-zip-format", regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.POLICY_ZIP_FORMAT));
|
||||||
|
|
||||||
defineRule("email-address-format",
|
|
||||||
regex(
|
|
||||||
/^([a-zA-Z0-9_\-.+]+)@([a-zA-Z0-9_\-.]+)\.([a-zA-Z]{2,})$/,
|
|
||||||
errorMessages.EMAIL_ADDRESS_FORMAT
|
|
||||||
));
|
|
||||||
|
|
||||||
defineRule("phone-number-format",
|
|
||||||
regex(
|
|
||||||
/^(\([0-9]{3}\)|[0-9]{3}) *[-.]? *[0-9]{3} *[-.]? *[0-9]{4}$/,
|
|
||||||
errorMessages.PHONE_NUMBER_FORMAT
|
|
||||||
));
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "welcome-page",
|
name: "welcome-page",
|
||||||
mixins: [BaseFormMixin],
|
mixins: [BaseFormMixin],
|
||||||
|
|
@ -206,6 +191,16 @@ export default {
|
||||||
return {
|
return {
|
||||||
welcomePageModel: this.getWelcomePageModelFromStore(),
|
welcomePageModel: this.getWelcomePageModelFromStore(),
|
||||||
vehiclesFound: [],
|
vehiclesFound: [],
|
||||||
|
rules: {
|
||||||
|
policyNumber: 'policy-number-required',
|
||||||
|
policyZip: 'policy-zip-required|policy-zip-format',
|
||||||
|
lossDate: 'loss-date-required',
|
||||||
|
damageOption: 'damage-option-required',
|
||||||
|
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`,
|
||||||
|
email: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
|
||||||
|
lossCity: 'loss-city-required',
|
||||||
|
lossState: 'loss-state-required'
|
||||||
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
|
|
||||||
34
src/main.js
34
src/main.js
|
|
@ -1,32 +1,32 @@
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import App from './App.vue';
|
import 'bootstrap/dist/js/bootstrap';
|
||||||
import router from './router';
|
|
||||||
import "../node_modules/bootstrap/dist/js/bootstrap.js";
|
|
||||||
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
|
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate';
|
||||||
import { useMainStore } from '@/store';
|
import { useMainStore } from '@/store';
|
||||||
import baseMixin from "@/mixins/base-mixin.js";
|
import baseMixin from '@/mixins/base-mixin';
|
||||||
import { createPinia } from 'pinia';
|
import { createPinia } from 'pinia';
|
||||||
import Maska from "maska";
|
import Maska from 'maska';
|
||||||
import LoadScript from "vue-plugin-load-script";
|
import LoadScript from 'vue-plugin-load-script';
|
||||||
|
|
||||||
import analyticsMixin from "@/mixins/analytics-mixin.js";
|
import analyticsMixin from '@/mixins/analytics-mixin';
|
||||||
import experimentMixin from "@/mixins/experiment-mixin.js";
|
import experimentMixin from '@/mixins/experiment-mixin';
|
||||||
|
import defineGlobalRules from '@/helpers/global-rule-definer';
|
||||||
|
import router from './router';
|
||||||
|
import App from './App.vue';
|
||||||
|
|
||||||
// Vue App Setup
|
// Vue App Setup
|
||||||
const vueApp = createApp(App);
|
const vueApp = createApp(App);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Needed to make injections reactively linked to the provider.
|
* Needed to make injections reactively linked to the provider.
|
||||||
* This is not needed once Vue.js is in version 3.3
|
* This is not needed once Vue.js is in version 3.3
|
||||||
* https://vuejs.org/guide/components/provide-inject.html#working-with-reactivity
|
* https://vuejs.org/guide/components/provide-inject.html#working-with-reactivity
|
||||||
*/
|
*/
|
||||||
vueApp.config.unwrapInjectedRef = true;
|
vueApp.config.unwrapInjectedRef = true;
|
||||||
|
|
||||||
vueApp.config.compilerOptions.isCustomElement = (tag) => {
|
vueApp.config.compilerOptions.isCustomElement = (tag) =>
|
||||||
return (tag === 'siteSubHeader' ||
|
(tag === 'siteSubHeader'
|
||||||
tag === 'ServicePackages' ||
|
|| tag === 'ServicePackages'
|
||||||
tag === 'servicePackageQuestion');
|
|| tag === 'servicePackageQuestion');
|
||||||
}
|
|
||||||
|
|
||||||
// Pinia
|
// Pinia
|
||||||
const pinia = createPinia();
|
const pinia = createPinia();
|
||||||
|
|
@ -34,7 +34,6 @@ vueApp.use(pinia);
|
||||||
pinia.use(piniaPluginPersistedstate);
|
pinia.use(piniaPluginPersistedstate);
|
||||||
useMainStore().populateInitialState();
|
useMainStore().populateInitialState();
|
||||||
|
|
||||||
|
|
||||||
// Additional Vue items to setup
|
// Additional Vue items to setup
|
||||||
vueApp.use(router);
|
vueApp.use(router);
|
||||||
vueApp.use(Maska);
|
vueApp.use(Maska);
|
||||||
|
|
@ -43,4 +42,7 @@ vueApp.mixin(baseMixin);
|
||||||
vueApp.mixin(analyticsMixin);
|
vueApp.mixin(analyticsMixin);
|
||||||
vueApp.mixin(experimentMixin);
|
vueApp.mixin(experimentMixin);
|
||||||
|
|
||||||
vueApp.mount("#app");
|
vueApp.mount('#app');
|
||||||
|
|
||||||
|
// define global rules
|
||||||
|
defineGlobalRules();
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue