CSR-343 Finish validation

This commit is contained in:
Katie 2022-06-28 11:17:57 -04:00
parent 8a1fc5bbe5
commit 06335ba625
5 changed files with 137 additions and 77 deletions

View file

@ -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;

View file

@ -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()
}
}
};

View file

@ -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() {

View file

@ -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()"
>

View file

@ -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%;