Merge remote-tracking branch 'origin/develop' into feature/INSR-7771
This commit is contained in:
commit
1675f10e66
7 changed files with 227 additions and 328 deletions
BIN
src/assets/img/tints/GlassTint.png
Normal file
BIN
src/assets/img/tints/GlassTint.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.8 KiB |
|
|
@ -1,91 +0,0 @@
|
|||
// TintMap with array keys by location, lowercase to avoid as much string mismatching as possible.
|
||||
// Src assumes you have a @/assets/img/tints/, making the final value @/assets/img/tints/{Src} in the markup.
|
||||
// See vehicle-parts for implementation example.
|
||||
const tintMap = Object.freeze({
|
||||
other: [
|
||||
// Blue Shade
|
||||
{ name: 'blue tint, blue shade', src: 'Glass-BlueShade-BlueTint.svg' },
|
||||
{ name: 'brown tint, blue shade', src: 'Glass-BlueShade-BrownTint.svg' },
|
||||
{ name: 'gray tint, blue shade', src: 'Glass-BlueShade-GrayTint.svg' },
|
||||
{ name: 'green tint, blue shade', src: 'Glass-BlueShade-GreenTint.svg' },
|
||||
{ name: 'clear, blue shade', src: 'Glass-BlueShade-NoTint.svg' },
|
||||
|
||||
// Brown Shade
|
||||
{ name: 'brown tint, brown shade', src: 'Glass-BrownShade-BrownTint.svg' },
|
||||
|
||||
// Gray Shade
|
||||
{ name: 'blue tint, gray shade', src: 'Glass-GrayShade-BlueTint.svg' },
|
||||
{ name: 'brown tint, gray shade', src: 'Glass-GrayShade-BrownTint.svg' },
|
||||
{ name: 'gray tint, gray shade', src: 'Glass-GrayShade-GrayTint.svg' },
|
||||
{ name: 'green tint, gray shade', src: 'Glass-GrayShade-GreenTint.svg' },
|
||||
|
||||
// Green Shade
|
||||
{ name: 'blue tint, green shade', src: 'Glass-GreenShade-BlueTint.svg' },
|
||||
{ name: 'brown tint, green shade', src: 'Glass-GreenShade-BrownTint.svg' },
|
||||
{ name: 'green tint, green shade', src: 'Glass-GreenShade-GreenTint.svg' },
|
||||
|
||||
// Tints Only
|
||||
{ name: 'blue tint privacy', src: 'Glass-NoShade-BlueTint.svg' },
|
||||
{ name: 'bronze tint', src: 'Glass-NoShade-BrownTint.svg' },
|
||||
{ name: 'dark brown tint', src: 'Glass-NoShade-DarkBrownTint.svg' },
|
||||
{ name: 'privacy, black frame', src: 'Glass-NoShade-Privacy.svg' },
|
||||
{ name: 'gray tint', src: 'Glass-NoShade-GrayTint.svg' },
|
||||
{ name: 'green tint', src: 'Glass-NoShade-GreenTint.svg' },
|
||||
{ name: 'gray tint privacy', src: 'Glass-NoShade-GrayTint.svg' },
|
||||
{ name: 'blue tint', src: 'Glass-NoShade-BlueTint.svg' },
|
||||
{ name: 'green tint privacy', src: 'Glass-NoShade-GreenTint.svg' },
|
||||
|
||||
// No shade or tint
|
||||
{ name: 'clear', src: 'Glass-NoShade-NoTint.svg' }
|
||||
],
|
||||
|
||||
windshield: [
|
||||
// Blue Shade
|
||||
{ name: 'blue tint, blue shade', src: 'Windshield-BlueShade-BlueTint.svg' },
|
||||
{ name: 'bronze tint, blue shade', src: 'Windshield-BlueShade-BrownTint.svg' },
|
||||
{ name: 'gray tint, blue shade', src: 'Windshield-BlueShade-GrayTint.svg' },
|
||||
{ name: 'green tint, blue shade', src: 'Windshield-BlueShade-GreenTint.svg' },
|
||||
{ name: 'clear, blue shade', src: 'Windshield-BlueShade-NoTint.svg' },
|
||||
|
||||
// Brown Shade
|
||||
{ name: 'bronze tint, bronze shade', src: 'Windshield-BrownShade-BrownTint.svg' },
|
||||
|
||||
// Gray Shade
|
||||
{ name: 'blue tint, gray shade', src: 'Windshield-GrayShade-BlueTint.svg' },
|
||||
{ name: 'brown tint, gray shade', src: 'Windshield-GrayShade-BrownTint.svg' },
|
||||
{ name: 'gray tint, gray shade', src: 'Windshield-GrayShade-GrayTint.svg' },
|
||||
{ name: 'green tint, gray shade', src: 'Windshield-GrayShade-GreenTint.svg' },
|
||||
|
||||
// Green Shade
|
||||
{ name: 'blue tint, green shade', src: 'Windshield-GreenShade-BlueTint.svg' },
|
||||
{ name: 'brown tint, green shade', src: 'Windshield-GreenShade-BrownTint.svg' },
|
||||
{ name: 'green tint, green shade', src: 'Windshield-GreenShade-GreenTint.svg' },
|
||||
|
||||
// Tints Only
|
||||
{ name: 'blue tint', src: 'Windshield-NoShade-BlueTint.svg' },
|
||||
{ name: 'bronze tint', src: 'Windshield-NoShade-BrownTint.svg' },
|
||||
{ name: 'dark brown tint', src: 'Windshield-NoShade-DarkBrownTint.svg' },
|
||||
{ name: 'privacy, black frame', src: 'Windshield-NoShade-Privacy.svg' },
|
||||
{ name: 'gray tint', src: 'Windshield-NoShade-GrayTint.svg' },
|
||||
{ name: 'green tint', src: 'Windshield-NoShade-GreenTint.svg' },
|
||||
{ name: 'gray tint privacy', src: 'Windshield-NoShade-GrayTint.svg' },
|
||||
|
||||
// No shade or tint
|
||||
{ name: 'clear', src: 'Windshield-NoShade-NoTint.svg' }
|
||||
]
|
||||
});
|
||||
|
||||
// Gets the tint image source string given the glass location, and the tint description (like 'Green Tint')
|
||||
// Use lowered strings here to try to avoid mismatch. Returns an empty string if array key doesn't exist.
|
||||
// Returns undefined if no items are found.
|
||||
const getTintImage = (glassLocation, colorString) => {
|
||||
// Windshield glass has special images, all other glass uses the same though.
|
||||
const glassLoc = (glassLocation.toLowerCase() !== 'windshield') ? 'other' : 'windshield';
|
||||
if (tintMap[glassLoc] === undefined) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return tintMap[glassLoc].find((item) => item.name.toLowerCase() === colorString.toLowerCase());
|
||||
};
|
||||
|
||||
export default getTintImage;
|
||||
|
|
@ -46,7 +46,7 @@ export function createUnorderedListFromStringOfParagraphs(stringOfParagraphs) {
|
|||
*/
|
||||
export function toTitleCase(text) {
|
||||
let temp = text?.toLowerCase() ?? '';
|
||||
return temp.replace(/(^|\s|-)\S/g, (letter) => letter.toUpperCase());
|
||||
return temp.replace(/(^|\s|-|\/)\S/g, (letter) => letter.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -41,13 +41,14 @@ function setupMocks({ glassNameProp, glassLocationProp, colorAnswersProp, modelV
|
|||
|
||||
};
|
||||
|
||||
const wrapper = shallowMount(glassPartQuestion, mountOptions);
|
||||
|
||||
// Mock store
|
||||
const partsOrQuestions = pageData ?? { partsOrQuestions: [{ glassName: 'Stationary', glassLocation: 'Rear', parts: [] }] };
|
||||
useMainStore().pageData = jest.fn();
|
||||
useMainStore().pageData.mockReturnValue(partsOrQuestions);
|
||||
document.querySelector = jest.fn().mockReturnValue({ clicked: false, click: jest.fn() });
|
||||
|
||||
const wrapper = shallowMount(glassPartQuestion, mountOptions);
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
|
|
@ -62,36 +63,23 @@ describe('glass-part-question.vue', () => {
|
|||
window.console.log(wrapper.vm.featureListData['Green Tint'][0].Text);
|
||||
// Assert
|
||||
expect(Object.keys(wrapper.vm.featureListData).length).toBe(2);
|
||||
expect(wrapper.vm.featureListData['Green Tint'][0].Text).toBe('heated glass, solar, 1 hole');
|
||||
expect(wrapper.vm.featureListData['Green Tint'][0].Text).toBe('Heated glass, Solar, 1 Hole');
|
||||
expect(wrapper.vm.featureListData['Green Tint'][0].Name).toBe('DB12209GTYN');
|
||||
expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Text).toBe('heated glass, solar, 1 hole');
|
||||
expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Text).toBe('Heated glass, Solar, 1 Hole');
|
||||
expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Name).toBe('DB12209YPYN');
|
||||
});
|
||||
|
||||
test('Tint mapper, should get tint image by glassLocation and tintColor', async () => {
|
||||
test('Tint mapper, should get return css class based on tint color', async () => {
|
||||
// Arrange
|
||||
|
||||
const { wrapper } = setupMocks(featureListData);
|
||||
|
||||
// Act
|
||||
await wrapper.vm.$nextTick();
|
||||
const tintSourceImage = wrapper.vm.getTintSourceImage('Rear', 'Green Tint');
|
||||
const tintClass = wrapper.vm.convertTintToCSSClass('Green Tint');
|
||||
|
||||
// Assert
|
||||
expect(tintSourceImage).toBe('Glass-NoShade-GreenTint.svg');
|
||||
});
|
||||
|
||||
test('Tint mapper, should return empty string if no tint map found', async () => {
|
||||
// Arrange
|
||||
|
||||
const { wrapper } = setupMocks(featureListData);
|
||||
|
||||
// Act
|
||||
await wrapper.vm.$nextTick();
|
||||
const tintSourceImage = wrapper.vm.getTintSourceImage('Rear', 'Crazy Rainbow Tint');
|
||||
|
||||
// Assert
|
||||
expect(tintSourceImage).toBe('');
|
||||
expect(tintClass).toBe('green-tint');
|
||||
});
|
||||
|
||||
test('Should emit updateModelValue, and have correct attributes', async () => {
|
||||
|
|
@ -122,7 +110,7 @@ describe('glass-part-question.vue', () => {
|
|||
{ partNumber: 'DB12209GTYN', color: 'Green Tint' }
|
||||
]);
|
||||
expect(listCard.attributes('groupname')).toBe('Rear-Stationary');
|
||||
expect(listCard.attributes('validationrules')).toBe('Rear-Stationary-tint-required');
|
||||
expect(listCard.attributes('validationrules')).toBe('Rear-Stationary-part-required');
|
||||
});
|
||||
|
||||
test('default is selected if only one option', async () => {
|
||||
|
|
@ -136,58 +124,42 @@ describe('glass-part-question.vue', () => {
|
|||
}
|
||||
]
|
||||
};
|
||||
const updateSpy = jest.spyOn(glassPartQuestion.methods, 'updateSelectedPartNumber');
|
||||
const { wrapper } = setupMocks(featureListData);
|
||||
|
||||
// Act
|
||||
await wrapper.vm.$nextTick();
|
||||
await wrapper.setData({ selectedTint: 'Green Tint' });
|
||||
// take emitted value, pass down as modelValue
|
||||
// yes, yes, it's not ideal
|
||||
await wrapper.setProps({ modelValue: wrapper.emitted()['update:modelValue'][0][0] });
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.selectedPartNumber).toBe('DB12209GTYN');
|
||||
expect(updateSpy).toHaveBeenCalledWith('DB12209GTYN');
|
||||
});
|
||||
|
||||
const partsForSelectedTintTestCases = [
|
||||
const partsForLocationTestCases = [
|
||||
[
|
||||
'Rear',
|
||||
'Stationary',
|
||||
'Green Tint',
|
||||
[
|
||||
{ partNumber: 'Glass1', color: 'Green Tint' },
|
||||
{ partNumber: 'Glass2', color: 'Blue Tint' },
|
||||
{ partNumber: 'Glass3', color: 'Green Tint' },
|
||||
{ partNumber: 'Glass4', color: 'Green Tint' },
|
||||
{ partNumber: 'Glass6', color: 'Green Tint' }
|
||||
{ partNumber: 'Glass5', color: 'Blue Tint' },
|
||||
{ partNumber: 'Glass6', color: 'Green Tint' },
|
||||
{ partNumber: 'Glass7', color: 'Red Tint' }
|
||||
]
|
||||
],
|
||||
[
|
||||
'Rear',
|
||||
'Stationary',
|
||||
'Blue Tint',
|
||||
[
|
||||
{ partNumber: 'Glass2', color: 'Blue Tint' },
|
||||
{ partNumber: 'Glass5', color: 'Blue Tint' }
|
||||
]
|
||||
],
|
||||
['Rear', 'Stationary', 'Red Tint', [{ partNumber: 'Glass7', color: 'Red Tint' }]],
|
||||
[
|
||||
'Windshield',
|
||||
'Single',
|
||||
'Green Tint',
|
||||
[
|
||||
{ partNumber: 'Windshield1', color: 'Green Tint' },
|
||||
{ partNumber: 'Windshield2', color: 'Green Tint' }
|
||||
]
|
||||
],
|
||||
['Windshield', 'Single', 'Blue Tint', []],
|
||||
['Driver', 'Quarter', 'Green Tint', []]
|
||||
['Driver', 'Quarter', []]
|
||||
];
|
||||
|
||||
test.each(partsForSelectedTintTestCases)(
|
||||
'partsForSelectedTint returns correct parts',
|
||||
async (glassLocation, glassName, selectedTint, expectedResults) => {
|
||||
test.each(partsForLocationTestCases)(
|
||||
'partsForLocation returns correct parts',
|
||||
async (glassLocation, glassName, expectedResults) => {
|
||||
// Arrange
|
||||
const pageData = { partsOrQuestions: [
|
||||
{
|
||||
|
|
@ -219,11 +191,8 @@ describe('glass-part-question.vue', () => {
|
|||
pageData
|
||||
});
|
||||
|
||||
// Act
|
||||
await wrapper.setData({ selectedTint });
|
||||
|
||||
// Assert
|
||||
expect(expectedResults).toEqual(wrapper.vm.partsForSelectedTint);
|
||||
expect(wrapper.vm.partsForLocation).toEqual(expectedResults);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,44 +1,27 @@
|
|||
<template>
|
||||
<div class="row">
|
||||
<p class="mb-0 color-question-text">
|
||||
{{ colorQuestionText }}
|
||||
</p>
|
||||
<span class="glass-location-text">
|
||||
{{ partType }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="nested-radio">
|
||||
<div class="row my-2">
|
||||
<div class="col">
|
||||
<buttonQuestion
|
||||
v-model="selectedTint"
|
||||
:answers="tintSelectionOptions"
|
||||
buttonTypeString="listCard"
|
||||
:isWide="true"
|
||||
altText=""
|
||||
isRequired
|
||||
:groupName="replaceAllSpaceWithDash(`${glassLocation}-${glassName}`)"
|
||||
:validationRules="tintValidationRules">
|
||||
<div
|
||||
class="row my-2"
|
||||
aria-live="polite">
|
||||
<div class="col">
|
||||
<buttonQuestion
|
||||
id="glass-part-question"
|
||||
v-model="selectedPartNumber"
|
||||
buttonTypeString="radio"
|
||||
class="radioQuestion"
|
||||
:questionText="glassFeatureQuestion"
|
||||
:answers="featureListData[selectedTint]"
|
||||
textPosition="text-start"
|
||||
:loaderEnabled="false"
|
||||
isRequired
|
||||
isSmallQuestionText
|
||||
:groupName="replaceAllSpaceWithDash(`${glassLocation}-${glassName}-${selectedTint}`)"
|
||||
:validationRules="partValidationRules" />
|
||||
</div>
|
||||
</div>
|
||||
</buttonQuestion>
|
||||
</div>
|
||||
<template
|
||||
v-for="(tint, index) in tintSelectionOptions"
|
||||
:key="index">
|
||||
<div class="tint-option">
|
||||
<span>{{ `${partType} - ${tint}` }}</span>
|
||||
<span :class="`tint-image ${convertTintToCSSClass(tint)}`"></span>
|
||||
</div>
|
||||
</div>
|
||||
<buttonQuestion
|
||||
id="glass-part-question"
|
||||
v-model="selectedPartNumber"
|
||||
buttonTypeString="list-button"
|
||||
class="radioQuestion"
|
||||
:answers="featureListData[tint]"
|
||||
:loaderEnabled="false"
|
||||
isRequired
|
||||
:groupName="replaceAllSpaceWithDash(`${glassLocation}-${glassName}`)"
|
||||
:validationRules="partValidationRules" />
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -46,12 +29,10 @@
|
|||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
|
||||
// Supporting files
|
||||
import getTintImage from '@/constants/tint-mapper';
|
||||
import getCustomTransformValue from '@/constants/dynamictext-mapper';
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import { useMainStore } from '@/store';
|
||||
import { toTitleCase } from '@/helpers/text-helper';
|
||||
|
||||
export default {
|
||||
name: 'glass-part-question',
|
||||
|
|
@ -72,42 +53,21 @@ export default {
|
|||
emits: ['update:modelValue'],
|
||||
data() {
|
||||
return {
|
||||
glassColorQuestion: '',
|
||||
glassFeatureQuestion: '',
|
||||
selectedTint: ''
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
tintValidationRules() {
|
||||
const validationRuleName = `${this.glassLocation}-${this.glassName}-tint-required`;
|
||||
|
||||
defineRule(validationRuleName, required(errorMessages.OPTION_REQUIRED));
|
||||
|
||||
return validationRuleName;
|
||||
},
|
||||
partValidationRules() {
|
||||
const validationRuleName = `${this.glassLocation}-${this.glassName}-part-required`;
|
||||
|
||||
defineRule(validationRuleName, required(errorMessages.OPTION_REQUIRED));
|
||||
return validationRuleName;
|
||||
},
|
||||
colorQuestionText() {
|
||||
return getCustomTransformValue(
|
||||
this.glassColorQuestion,
|
||||
`${this.glassLocation} ${this.glassName}`
|
||||
);
|
||||
},
|
||||
|
||||
tintSelectionOptions() {
|
||||
const tintOptions = [];
|
||||
|
||||
Object.keys(this.featureListData).forEach((tintOption) => {
|
||||
const buttonImage = this.getTintSourceImage(this.glassLocation, tintOption);
|
||||
tintOptions.push({
|
||||
value: tintOption,
|
||||
buttonLabel: tintOption,
|
||||
buttonImage: buttonImage ? require(`@/assets/img/tints/${buttonImage}`) : null
|
||||
});
|
||||
tintOptions.push(tintOption);
|
||||
});
|
||||
|
||||
return tintOptions;
|
||||
|
|
@ -115,21 +75,21 @@ export default {
|
|||
|
||||
selectedPartNumber: {
|
||||
get() {
|
||||
return this.modelValue?.partNumber;
|
||||
return this.modelValue?.partNumber ?? '';
|
||||
},
|
||||
set(newValue) {
|
||||
const part = this.partsForSelectedTint
|
||||
.filter((partItem) => partItem.partNumber === newValue?.value)[0];
|
||||
const part = this.partsForLocation
|
||||
.filter((partItem) => partItem.partNumber === newValue)[0];
|
||||
this.$emit('update:modelValue', part);
|
||||
}
|
||||
},
|
||||
|
||||
partsForSelectedTint() {
|
||||
partsForLocation() {
|
||||
const matchingGlass = this.PartDataFromApi.partsOrQuestions?.filter((dataForGlassLocationAndName) =>
|
||||
dataForGlassLocationAndName.glassName === this.glassName
|
||||
&& dataForGlassLocationAndName.glassLocation === this.glassLocation);
|
||||
const matchingGlassParts = matchingGlass?.length === 1 ? matchingGlass[0].parts : [];
|
||||
return matchingGlassParts.filter((part) => part.color === this.selectedTint) ?? [];
|
||||
return matchingGlassParts;
|
||||
},
|
||||
|
||||
// Creates a map of the feature list data in the correct Name/Value
|
||||
|
|
@ -142,7 +102,7 @@ export default {
|
|||
|
||||
// Map the data to Name/Text object for ButtonQuestion
|
||||
const mappedItem = item.FeatureAnswers.reduce((featureArr, it) => {
|
||||
featureArr.Text = it.FeatureAnswerText; // Display to User
|
||||
featureArr.Text = this.toTitleCaseWithExceptions(it.FeatureAnswerText); // Display to User
|
||||
featureArr.Name = it.PartNumber; // Backing Value
|
||||
|
||||
return featureArr;
|
||||
|
|
@ -158,72 +118,19 @@ export default {
|
|||
|
||||
PartDataFromApi() {
|
||||
return this.mainStore.pageData(this.$route.query.issPage) ?? {};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedTint() {
|
||||
this.AutoSelectIfSinglePart();
|
||||
},
|
||||
|
||||
partType() {
|
||||
const type = this.partsForLocation?.[0]?.partType ?? '';
|
||||
return toTitleCase(type);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.LoadPreselectedValues();
|
||||
this.AutoSelectIfSinglePart();
|
||||
},
|
||||
methods: {
|
||||
// Initialize the component data
|
||||
initializeComponent(cmsContent) {
|
||||
this.glassColorQuestion = cmsContent.ColorQuestionWidget.QuestionText;
|
||||
this.glassFeatureQuestion = cmsContent.FeatureQuestionWidget.QuestionText;
|
||||
},
|
||||
|
||||
// Gets tint images based on the glass type, and tint name.
|
||||
// Returns an empty string if the src or object is undefined.
|
||||
getTintSourceImage(glassLocation, tintColor) {
|
||||
const tintSourceObject = getTintImage(glassLocation, tintColor);
|
||||
|
||||
if (tintSourceObject === undefined || !tintSourceObject.src) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return tintSourceObject.src;
|
||||
},
|
||||
|
||||
AutoSelectIfSinglePart() {
|
||||
if (this.partsForSelectedTint?.length > 0) {
|
||||
// Check if only a single part is present for the tint and set the v-model if it is.
|
||||
if (this.partsForSelectedTint?.length === 1) {
|
||||
// select element with matching partNumber
|
||||
this.updateSelectedPartNumber(this.partsForSelectedTint[0].partNumber);
|
||||
} else {
|
||||
this.selectedPartNumber = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Loads the preselected values from the store.
|
||||
LoadPreselectedValues() {
|
||||
this.$nextTick(() => {
|
||||
// Populate button-question model-value if parts data already exists in store
|
||||
if (this.modelValue !== undefined) {
|
||||
this.selectedTint = this.modelValue.color;
|
||||
const { glassParts } = useMainStore().order.lineItems;
|
||||
if (glassParts) {
|
||||
for (const tintPart of this.partsForSelectedTint) {
|
||||
for (const glassPart of glassParts) {
|
||||
if (tintPart.partNumber === glassPart.partNumber) {
|
||||
this.$nextTick(() => {
|
||||
this.updateSelectedPartNumber(tintPart.partNumber);
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
updateSelectedPartNumber(partNumber) {
|
||||
this.selectedPartNumber = { value: partNumber };
|
||||
this.selectedPartNumber = partNumber;
|
||||
this.$nextTick(() => {
|
||||
const radioInput = document.querySelector(`input[value=${this.selectedPartNumber}]`);
|
||||
// Fire a click event on the input so the field is updated
|
||||
|
|
@ -231,37 +138,128 @@ export default {
|
|||
});
|
||||
},
|
||||
|
||||
AutoSelectIfSinglePart() {
|
||||
if (this.partsForLocation?.length > 0) {
|
||||
// Check if only a single part is present for the tint and set the v-model if it is.
|
||||
if (this.partsForLocation?.length === 1) {
|
||||
// select element with matching partNumber
|
||||
this.updateSelectedPartNumber(this.partsForLocation[0].partNumber);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
replaceAllSpaceWithDash(str) {
|
||||
return String(str).replaceAll(' ', '-');
|
||||
},
|
||||
convertTintToCSSClass(tint) {
|
||||
return tint.toLowerCase().replaceAll(' ', '-').replaceAll(',', '');
|
||||
},
|
||||
toTitleCaseWithExceptions(text) {
|
||||
const exceptions = ['side', 'glass', 'dimming'];
|
||||
let temp = toTitleCase(text);
|
||||
exceptions.forEach((exception) => {
|
||||
const regEx = new RegExp(exception, 'ig');
|
||||
temp = temp.replace(regEx, exception);
|
||||
});
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.nested-radio {
|
||||
:deep(.ui-radio) {
|
||||
flex-direction: column;
|
||||
margin: 0.25rem 0;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 0.875rem;
|
||||
}
|
||||
}
|
||||
|
||||
.color-question-text {
|
||||
color: $black;
|
||||
.glass-location-text {
|
||||
font-weight: $font-weight-bold;
|
||||
color: $black;
|
||||
}
|
||||
.tint-option {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
height: 2rem;
|
||||
margin-top: .5rem;
|
||||
margin-bottom: .25rem;
|
||||
font-weight: 600;
|
||||
color: $black;
|
||||
|
||||
#glass-part-question {
|
||||
span.fw-bold.w-100 {
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0;
|
||||
@include media-breakpoint-up(md) {
|
||||
justify-content: flex-start;
|
||||
}
|
||||
div.col.radio-button-container {
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.radioQuestion {
|
||||
:deep(.list-button) {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
.tint-image {
|
||||
width: 2rem;
|
||||
height: 2rem;
|
||||
margin-left: 1rem;
|
||||
margin-top: -.25rem;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url(~@/assets/img/tints/GlassTint.png);
|
||||
}
|
||||
.blue-tint-green-shade {
|
||||
background-position: -53px -53px;
|
||||
}
|
||||
.blue-tint-blue-shade {
|
||||
background-position: -160px -53px;
|
||||
}
|
||||
.gray-tint-gray-shade {
|
||||
background-position: -267px -53px;
|
||||
}
|
||||
.blue-tint {
|
||||
background-position: -373px -53px;
|
||||
}
|
||||
.gray-tint {
|
||||
background-position: -480px -53px;
|
||||
}
|
||||
.green-tint-green-shade {
|
||||
background-position: -53px -160px;
|
||||
}
|
||||
.green-tint-blue-shade {
|
||||
background-position: -160px -160px;
|
||||
}
|
||||
.green-tint-gray-shade {
|
||||
background-position: -267px -160px;
|
||||
}
|
||||
.green-tint {
|
||||
background-position: -373px -160px;
|
||||
}
|
||||
.clear {
|
||||
background-position: -480px -160px;
|
||||
}
|
||||
.bronze-tint-green-shade {
|
||||
background-position: -53px -266px;
|
||||
}
|
||||
.bronze-tint-blue-shade {
|
||||
background-position: -160px -266px;
|
||||
}
|
||||
.bronze-tint-gray-shade {
|
||||
background-position: -267px -266px;
|
||||
}
|
||||
.bronze-tint-bronze-shade {
|
||||
background-position: -373px -266px;
|
||||
}
|
||||
.bronze-tint {
|
||||
background-position: -480px -266px;
|
||||
}
|
||||
.bronze-tint-privacy {
|
||||
background-position: -587px -266px;
|
||||
}
|
||||
.clear-blue-shade {
|
||||
background-position: -53px -373px;
|
||||
}
|
||||
.gray-tint-blue-shade {
|
||||
background-position: -160px -373px;
|
||||
}
|
||||
.blue-tint-gray-shade {
|
||||
background-position: -267px -373px;
|
||||
}
|
||||
.gray-tint-privacy {
|
||||
background-position: -373px -373px;
|
||||
}
|
||||
.tinted {
|
||||
background-position: -480px -373px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -11,34 +11,36 @@
|
|||
<div class="vehicle-parts-container iss-heritage-content-container-width">
|
||||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
class="mt-4"
|
||||
class="mt-4 subheader"
|
||||
cmsWidgetName="SiteSubHeaderWidget" />
|
||||
<alert
|
||||
id="vehicle-parts-alert"
|
||||
class="mt-3 mb-3"
|
||||
alertClass="alert-warning"
|
||||
cmsWidgetName="AlertWidget"
|
||||
:isDismissible="false" />
|
||||
<div
|
||||
v-for="(item, i) in PartsOrQuestions"
|
||||
:key="i">
|
||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||
<hr v-if="i > 0" />
|
||||
<glassPartQuestion
|
||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
|
||||
:glassLocation="item.glassLocation"
|
||||
:glassName="item.glassName"
|
||||
:colorAnswers="item.colorAnswers"
|
||||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
||||
<div class="body-container">
|
||||
<div
|
||||
v-for="(item, i) in PartsOrQuestions"
|
||||
:key="i"
|
||||
class="glass-question-container">
|
||||
<glassPartQuestion
|
||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||
v-model="selectedGlassParts[item.glassLocation + '-' + item.glassName]"
|
||||
:glassLocation="item.glassLocation"
|
||||
:glassName="item.glassName"
|
||||
:colorAnswers="item.colorAnswers"
|
||||
:alreadyPopulatedPartsData="alreadyPopulatedPartsData" />
|
||||
</div>
|
||||
</div>
|
||||
<siteFooter
|
||||
ref="siteFooter"
|
||||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="isForwardActionDisabled"
|
||||
@backClicked="navigateBackByVehicleQuestions"
|
||||
@ForwardClicked="forwardButtonAction" />
|
||||
<div class="need-help-link-container">
|
||||
<textLink
|
||||
v-if="needHelpLinkText"
|
||||
linkType="navigation"
|
||||
:text="needHelpLinkText"
|
||||
href="#"
|
||||
@clickEvent="requestCallbackBailout" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -51,7 +53,7 @@ import glassPartQuestion from '@/layouts/vehicle-parts/glass-part-question/glass
|
|||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||
|
||||
// Supporting Files
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
|
|
@ -61,6 +63,7 @@ import { Form } from 'vee-validate';
|
|||
import vehicleQuestionsMixin from '@/mixins/vehicle-questions-mixin';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import widgetFields from '@/constants/cms-widget-fields';
|
||||
|
||||
export default {
|
||||
name: 'vehicle-parts',
|
||||
|
|
@ -71,7 +74,7 @@ export default {
|
|||
siteHeader,
|
||||
siteSubHeader,
|
||||
siteFooter,
|
||||
alert
|
||||
textLink
|
||||
},
|
||||
mixins: [BaseFormMixin, vehicleQuestionsMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -88,17 +91,6 @@ export default {
|
|||
// Call the "next" function to complete the transition to this page.
|
||||
next((vm) => {
|
||||
vm.setCmsContent(resultMap.cmsContent);
|
||||
|
||||
// Glass Part Question dynamic component
|
||||
Object.keys(vm.$refs)
|
||||
.filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined)
|
||||
.forEach((c) =>
|
||||
vm.$refs[c][0].initializeComponent({
|
||||
ColorQuestionWidget:
|
||||
resultMap.cmsContent.ColorQuestionWidget,
|
||||
FeatureQuestionWidget:
|
||||
resultMap.cmsContent.FeatureQuestionWidget
|
||||
}));
|
||||
});
|
||||
},
|
||||
data() {
|
||||
|
|
@ -156,6 +148,9 @@ export default {
|
|||
|
||||
RefPrefix() {
|
||||
return 'partQuestion';
|
||||
},
|
||||
needHelpLinkText() {
|
||||
return this.getCmsContent('NeedHelpLinkWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -220,23 +215,47 @@ export default {
|
|||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
requestCallbackBailout() {
|
||||
this.mainStore.setBailout(bailoutMessage.RequestCallback());
|
||||
this.$router.navigate(navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT, this.$route);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.iss-heritage-container-width {
|
||||
#app .iss-heritage-container-width {
|
||||
.iss-heritage-content-container-width {
|
||||
@include media-breakpoint-up(md) {
|
||||
width: 58.33333333%;
|
||||
}
|
||||
}
|
||||
|
||||
.vehicle-parts-container {
|
||||
position: relative;
|
||||
min-height: 1px;
|
||||
padding-left: .9375rem;
|
||||
padding-right: .9375rem;
|
||||
|
||||
#vehicle-parts-alert {
|
||||
.alert-heading {
|
||||
margin-top: 0.25rem !important;
|
||||
.subheader {
|
||||
:deep(strong) {
|
||||
text-transform: uppercase;
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
|
||||
.glass-question-container {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
|
||||
.body-container {
|
||||
margin-bottom: 1.875rem;
|
||||
}
|
||||
|
||||
.need-help-link-container {
|
||||
margin-bottom: 2.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -248,6 +248,10 @@ const routingTable = () => [
|
|||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_NO_MORE_QUESTIONS,
|
||||
destinationIssPageValue: issPageValues.COVERAGE_STATEMENT
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_NEED_HELP_WITH_BAILOUT,
|
||||
destinationIssPageValue: issPageValues.BAILOUT_PAGE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue