CSR-343 Finish validation
This commit is contained in:
parent
8a1fc5bbe5
commit
06335ba625
5 changed files with 137 additions and 77 deletions
|
|
@ -9,8 +9,8 @@
|
|||
<legend class="sr-only" :data-focus-target="groupName" :id="groupName" tabindex="-1">
|
||||
{{(isMultiSelect && answers && answers.length > 1) ? 'Select one or more options below.' : 'Select an option below.' }}
|
||||
</legend>
|
||||
<div :class="getComponentWrapperClasses">
|
||||
<div :class="isWide ? 'col-12' : 'col'" v-for="answer in answers" :key="answer.Name ? answer.Name : answer">
|
||||
<div :class="getComponentLoopWrapperClasses">
|
||||
<div :class="getComponentWrapperClasses" v-for="answer in answers" :key="answer.Name ? answer.Name : answer">
|
||||
<component
|
||||
:is="buttonType"
|
||||
@isCheckedChanged="handleCheckedChanged"
|
||||
|
|
@ -108,7 +108,7 @@ export default {
|
|||
return "";
|
||||
}
|
||||
},
|
||||
getComponentWrapperClasses() {
|
||||
getComponentLoopWrapperClasses() {
|
||||
let classes;
|
||||
switch (this.buttonType) {
|
||||
case "listButton":
|
||||
|
|
@ -126,6 +126,17 @@ export default {
|
|||
}
|
||||
return classes;
|
||||
},
|
||||
getComponentWrapperClasses() {
|
||||
let classes = "";
|
||||
|
||||
classes += this.isWide ? "col-12" : "col";
|
||||
|
||||
if (this.buttonType == "radio") {
|
||||
classes += " radio-button-container";
|
||||
}
|
||||
|
||||
return classes;
|
||||
},
|
||||
getColLength(){
|
||||
if(this.isWide) {
|
||||
return "12"
|
||||
|
|
@ -163,6 +174,8 @@ export default {
|
|||
this.selectedValues = val.value;
|
||||
}
|
||||
}
|
||||
|
||||
this.$emit("isCheckedChanged", val);
|
||||
},
|
||||
},
|
||||
components: {
|
||||
|
|
@ -188,6 +201,12 @@ export default {
|
|||
}
|
||||
.button-question {
|
||||
color: $black;
|
||||
|
||||
.radio-button-container {
|
||||
&:not(:last-child) {
|
||||
padding-bottom: map-get($spacers, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
.question-text {
|
||||
margin-top: 1.5rem;
|
||||
|
|
|
|||
|
|
@ -13,26 +13,25 @@
|
|||
altText=""
|
||||
isRequired
|
||||
:groupName="`${glassLocation}-${glassName}`"
|
||||
@isCheckedChanged="ResetTintAndPartSelections()"
|
||||
@isCheckedChanged="ResetTintAndPartSelections"
|
||||
validationRules="replace-options-required"
|
||||
>
|
||||
<div class="row my-2" aria-live="polite">
|
||||
<div class="col">
|
||||
<buttonQuestion
|
||||
v-model="selectedPart"
|
||||
buttonType="radio"
|
||||
class="radioQuestion"
|
||||
:questionText="glassFeatureQuestion"
|
||||
:answers="featureListData[selectedTint]"
|
||||
:selectedValues="selectedPart"
|
||||
textPosition="text-start"
|
||||
:loaderEnabled="false"
|
||||
isRequired
|
||||
:groupName="`${glassLocation}-${glassName}-${selectedTint}`"
|
||||
validationRules="part-required"
|
||||
/>
|
||||
</div>
|
||||
<div class="row my-2" aria-live="polite">
|
||||
<div class="col">
|
||||
<buttonQuestion
|
||||
v-model="selectedPartNumber"
|
||||
buttonType="radio"
|
||||
class="radioQuestion"
|
||||
:questionText="glassFeatureQuestion"
|
||||
:answers="featureListData[selectedTint]"
|
||||
textPosition="text-start"
|
||||
:loaderEnabled="false"
|
||||
isRequired
|
||||
:groupName="`${glassLocation}-${glassName}-${selectedTint}`"
|
||||
:validationRules="`${glassLocation}-${glassName}-part-required`"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</buttonQuestion>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -58,7 +57,8 @@ import { errorMessages } from "@/constants/error-messages";
|
|||
// import { ErrorMessage } from "vee-validate";
|
||||
|
||||
defineRule("replace-options-required", required(errorMessages.OPTION_REQUIRED));
|
||||
defineRule("part-required", required(errorMessages.OPTION_REQUIRED));
|
||||
// defineRule("part-required", required(errorMessages.OPTION_REQUIRED));
|
||||
defineRule(`${this.glassLocation}-${this.glassName}-part-required`, required(errorMessages.OPTION_REQUIRED));
|
||||
|
||||
export default {
|
||||
name: "glass-part-question",
|
||||
|
|
@ -78,6 +78,7 @@ export default {
|
|||
// validationRules: String,
|
||||
},
|
||||
mounted() {
|
||||
// this.setAllValidationRules();
|
||||
this.LoadPreselectedValues();
|
||||
},
|
||||
components: {
|
||||
|
|
@ -108,15 +109,26 @@ export default {
|
|||
return tintOptions;
|
||||
},
|
||||
|
||||
selectedPart: {
|
||||
get: function () {
|
||||
return this.modelValue;
|
||||
selectedPartNumber: {
|
||||
get() {
|
||||
console.log(this.modelValue)
|
||||
return this.modelValue?.partNumber;
|
||||
},
|
||||
set: function (newValue) {
|
||||
this.$emit("update:modelValue", newValue);
|
||||
set(newValue) {
|
||||
console.log("setting")
|
||||
console.log(newValue)
|
||||
|
||||
this.$emit("update:modelValue", this.partsForSelectedTint.filter(part => part.partNumber == newValue)[0]);
|
||||
},
|
||||
},
|
||||
|
||||
partsForSelectedTint() {
|
||||
return this.PartDataFromApi.partsOrQuestions.filter(dataForGlassLocationAndName =>
|
||||
dataForGlassLocationAndName.glassName == this.glassName &&
|
||||
dataForGlassLocationAndName.glassLocation == this.glassLocation)[0]
|
||||
.parts.filter(part => part.color == this.selectedTint);
|
||||
},
|
||||
|
||||
// Creates a map of the feature list data in the correct Name/Value
|
||||
// format for the button-question component.
|
||||
featureListData() {
|
||||
|
|
@ -176,34 +188,47 @@ export default {
|
|||
// Reset selections when tint changes for the same glass to ensure proper selection.
|
||||
// Also checks if only a single part is present for the tint.
|
||||
ResetTintAndPartSelections() {
|
||||
this.selectedTint = "";
|
||||
this.selectedPart = {};
|
||||
console.log("Resetting!")
|
||||
// this.selectedTint = "";
|
||||
this.selectedPartNumber = null;
|
||||
this.AutoSelectIfSinglePart();
|
||||
},
|
||||
|
||||
// Check if only a single part is present for the tint and set the v-model if it is.
|
||||
AutoSelectIfSinglePart() {
|
||||
// Check if the selected tint only has a single feature
|
||||
Object.keys(this.PartDataFromApi.partsOrQuestions ?? {}).forEach(
|
||||
(key) => {
|
||||
const currentGlassSelection =
|
||||
this.PartDataFromApi.partsOrQuestions[key];
|
||||
console.log("Autoselecting, my dear")
|
||||
console.log(this.PartDataFromApi.partsOrQuestions)
|
||||
console.log(this.glassName)
|
||||
console.log(this.glassLocation)
|
||||
console.log(this.selectedTint)
|
||||
console.log(this.partsForSelectedTint)
|
||||
|
||||
if (
|
||||
currentGlassSelection.glassName === this.glassName &&
|
||||
currentGlassSelection.glassLocation ===
|
||||
this.glassLocation
|
||||
) {
|
||||
if (currentGlassSelection.parts.length === 1) {
|
||||
this.selectedPart = {
|
||||
[currentGlassSelection.glassLocation]: [
|
||||
currentGlassSelection.parts[0].partNumber,
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
if (this.partsForSelectedTint?.length == 1) {
|
||||
console.log("One!")
|
||||
this.selectedPartNumber = this.partsForSelectedTint[0].partNumber;
|
||||
console.log(this.selectedPartNumber)
|
||||
}
|
||||
|
||||
// this.$nextTick()
|
||||
console.log(this.selectedPartNumber)
|
||||
|
||||
// Check if the selected tint only has a single feature
|
||||
// Object.keys(this.PartDataFromApi.partsOrQuestions ?? {}).forEach(
|
||||
// (key) => {
|
||||
// const currentGlassSelection =
|
||||
// this.PartDataFromApi.partsOrQuestions[key];
|
||||
|
||||
// if (
|
||||
// currentGlassSelection.glassName === this.glassName &&
|
||||
// currentGlassSelection.glassLocation ===
|
||||
// this.glassLocation
|
||||
// ) {
|
||||
// if (currentGlassSelection.parts.length === 1) {
|
||||
// this.selectedPartNumber = currentGlassSelection.parts[0].partNumber
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// );
|
||||
},
|
||||
|
||||
// Loads the preselected values from the store.
|
||||
|
|
@ -211,12 +236,10 @@ export default {
|
|||
this.$nextTick(() => {
|
||||
if (this.modelValue !== undefined) {
|
||||
// Populate button-question model-value if parts data already exists in VueX
|
||||
const alreadyPopulatedPartsData =
|
||||
this.$store.getters.lineItems.glassParts;
|
||||
const alreadyPopulatedPartsData = this.$store.getters.lineItems.glassParts;
|
||||
|
||||
Object.keys(alreadyPopulatedPartsData).forEach((key) => {
|
||||
const partNumber =
|
||||
alreadyPopulatedPartsData[key].partNumber;
|
||||
const partNumber = alreadyPopulatedPartsData[key].partNumber;
|
||||
const tintColor = alreadyPopulatedPartsData[key].color;
|
||||
|
||||
Object.keys(this.modelValue).forEach((key) => {
|
||||
|
|
@ -233,10 +256,20 @@ export default {
|
|||
}
|
||||
});
|
||||
},
|
||||
// setAllValidationRules() {
|
||||
// console.log("SETTING VALIDATION RULES")
|
||||
// console.log(this.PartDataFromApi.partsOrQuestions)
|
||||
// this.PartDataFromApi.partsOrQuestions.forEach(part => {
|
||||
// console.log(`${this.glassLocation}-${this.glassName}-${this.selectedTint}-part-required`)
|
||||
// defineRule(`${this.glassLocation}-${this.glassName}-part-required`, required(errorMessages.OPTION_REQUIRED));
|
||||
// })
|
||||
// }
|
||||
},
|
||||
watch: {
|
||||
selectedTint(newTint, previousTint) {
|
||||
this.selectedPart = null;
|
||||
selectedTint() {
|
||||
console.log("watch me")
|
||||
this.selectedPartNumber = null;
|
||||
this.AutoSelectIfSinglePart()
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -21,12 +21,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-for="(item, i) in PartsForQuestions" :key="i">
|
||||
{{ glassParts }}
|
||||
<div v-for="(item, i) in PartsOrQuestions" :key="i">
|
||||
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||
<div class="container-fluid">
|
||||
<hr v-if="i > 0" />
|
||||
</div>
|
||||
<hr v-if="i > 0" />
|
||||
<glassPartQuestion
|
||||
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||
v-model="glassParts[item.glassLocation + '-' + item.glassName]"
|
||||
|
|
@ -108,7 +106,7 @@ computed: {
|
|||
isForwardActionDisabled() {
|
||||
return !this.glassParts || Object.values(this.glassParts).filter(value => value).length === 0;
|
||||
},
|
||||
PartsForQuestions() {
|
||||
PartsOrQuestions() {
|
||||
const partsData = this.PartsFromApi;
|
||||
|
||||
// Map API result data, to vehicle-parts data structure
|
||||
|
|
@ -164,26 +162,35 @@ methods: {
|
|||
|
||||
// Match them to the parts from the API.
|
||||
this.PartsFromApi.partsOrQuestions.forEach(part => {
|
||||
const selectedPartNumberForGlassLocationAndName = this.glassParts[`${part.glassLocation}-${part.glassName}`];
|
||||
const selectedPartData = part.parts.filter(part => part.partNumber == selectedPartNumberForGlassLocationAndName);
|
||||
const selectedPartForGlassLocationAndName = this.glassParts[`${part.glassLocation}-${part.glassName}`];
|
||||
console.log(part)
|
||||
console.log(this.glassParts)
|
||||
console.log(`${part.glassLocation}-${part.glassName}`)
|
||||
console.log(selectedPartForGlassLocationAndName)
|
||||
const selectedPartData = part.parts.filter(part => selectedPartForGlassLocationAndName && part.partNumber == selectedPartForGlassLocationAndName?.partNumber)[0];
|
||||
|
||||
matchedParts.push(selectedPartData[0]);
|
||||
if (selectedPartData)
|
||||
matchedParts.push(selectedPartData);
|
||||
})
|
||||
|
||||
console.log(matchedParts)
|
||||
|
||||
// If no parts could be matched, throw an error.
|
||||
if (matchedParts.length === 0) {
|
||||
if (matchedParts.length !== this.PartsFromApi.length) {
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
throw new Error("Could not match any parts to the selected parts");
|
||||
}
|
||||
|
||||
this.$refs.funnelFooter.removeLoader();
|
||||
|
||||
// Save parts to the store.
|
||||
store.commit(storeMutations.UPDATE_GLASS_PARTS, matchedParts);
|
||||
|
||||
// // Navigate to the next page.
|
||||
// this.$router.navigateAfterSave(
|
||||
// this.navigationScenarios.SELECTED_PARTS,
|
||||
// this.$route
|
||||
// );
|
||||
// Navigate to the next page.
|
||||
this.$router.navigateAfterSave(
|
||||
this.navigationScenarios.SELECTED_PARTS,
|
||||
this.$route
|
||||
);
|
||||
},
|
||||
|
||||
resetDependentState() {
|
||||
|
|
@ -193,7 +200,7 @@ methods: {
|
|||
LoadInitialPartsData() {
|
||||
const partsData = this.PartsFromApi;
|
||||
const alreadyPopulatedPartsData = this.$store.getters.lineItems.glassParts === null ? {} : this.$store.getters.lineItems.glassParts;
|
||||
|
||||
|
||||
partsData.partsOrQuestions.map((g) => {
|
||||
// If the part is already populated, use the value from the store and populate the v-model.
|
||||
Object.keys(alreadyPopulatedPartsData).forEach((key) => {
|
||||
|
|
@ -206,7 +213,7 @@ methods: {
|
|||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<template>
|
||||
<div :class="'h-100 l' + colLength">
|
||||
<div :class="{'h-100': !isWide}">
|
||||
<div
|
||||
class="list-card w-100 rounded-3 d-flex align-items-center h-100"
|
||||
class="list-card w-100 rounded-3 d-flex align-items-center"
|
||||
:class="[
|
||||
isWide ? 'horizontal' : '',
|
||||
(errors.length > 0 || hasError) ? 'has-error' : '',
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
tabindex="-1"
|
||||
:for="buttonID"
|
||||
:aria-labelledby="buttonID"
|
||||
class="d-flex w-100 align-items-center px-2 h-100"
|
||||
class="d-flex w-100 align-items-center px-2"
|
||||
:class="getLabelClasses"
|
||||
@mouseup="triggerButton()"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -49,8 +49,8 @@ export default {
|
|||
},
|
||||
created() {
|
||||
if (this.selectedValues) {
|
||||
this.checkValue = this.selectedValues[0] === this.value;
|
||||
}else{
|
||||
this.checkValue = this.selectedValues === this.value;
|
||||
} else{
|
||||
this.checkValue = false;
|
||||
}
|
||||
},
|
||||
|
|
@ -86,12 +86,13 @@ export default {
|
|||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>yu78zas
|
||||
<style lang="scss" scoped>
|
||||
.form-check {
|
||||
.form-check-input {
|
||||
border: 1px solid $gray-500;
|
||||
border-radius: 100%;
|
||||
margin-right: 0.5rem;
|
||||
margin-top: 0.12rem;
|
||||
&:checked {
|
||||
background-color: $white;
|
||||
background-size: 71%;
|
||||
|
|
|
|||
Loading…
Reference in a new issue