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"> <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.' }} {{(isMultiSelect && answers && answers.length > 1) ? 'Select one or more options below.' : 'Select an option below.' }}
</legend> </legend>
<div :class="getComponentWrapperClasses"> <div :class="getComponentLoopWrapperClasses">
<div :class="isWide ? 'col-12' : 'col'" v-for="answer in answers" :key="answer.Name ? answer.Name : answer"> <div :class="getComponentWrapperClasses" v-for="answer in answers" :key="answer.Name ? answer.Name : answer">
<component <component
:is="buttonType" :is="buttonType"
@isCheckedChanged="handleCheckedChanged" @isCheckedChanged="handleCheckedChanged"
@ -108,7 +108,7 @@ export default {
return ""; return "";
} }
}, },
getComponentWrapperClasses() { getComponentLoopWrapperClasses() {
let classes; let classes;
switch (this.buttonType) { switch (this.buttonType) {
case "listButton": case "listButton":
@ -126,6 +126,17 @@ export default {
} }
return classes; return classes;
}, },
getComponentWrapperClasses() {
let classes = "";
classes += this.isWide ? "col-12" : "col";
if (this.buttonType == "radio") {
classes += " radio-button-container";
}
return classes;
},
getColLength(){ getColLength(){
if(this.isWide) { if(this.isWide) {
return "12" return "12"
@ -163,6 +174,8 @@ export default {
this.selectedValues = val.value; this.selectedValues = val.value;
} }
} }
this.$emit("isCheckedChanged", val);
}, },
}, },
components: { components: {
@ -188,6 +201,12 @@ export default {
} }
.button-question { .button-question {
color: $black; color: $black;
.radio-button-container {
&:not(:last-child) {
padding-bottom: map-get($spacers, 2);
}
}
} }
.question-text { .question-text {
margin-top: 1.5rem; margin-top: 1.5rem;

View file

@ -13,26 +13,25 @@
altText="" altText=""
isRequired isRequired
:groupName="`${glassLocation}-${glassName}`" :groupName="`${glassLocation}-${glassName}`"
@isCheckedChanged="ResetTintAndPartSelections()" @isCheckedChanged="ResetTintAndPartSelections"
validationRules="replace-options-required" validationRules="replace-options-required"
> >
<div class="row my-2" aria-live="polite"> <div class="row my-2" aria-live="polite">
<div class="col"> <div class="col">
<buttonQuestion <buttonQuestion
v-model="selectedPart" v-model="selectedPartNumber"
buttonType="radio" buttonType="radio"
class="radioQuestion" class="radioQuestion"
:questionText="glassFeatureQuestion" :questionText="glassFeatureQuestion"
:answers="featureListData[selectedTint]" :answers="featureListData[selectedTint]"
:selectedValues="selectedPart" textPosition="text-start"
textPosition="text-start" :loaderEnabled="false"
:loaderEnabled="false" isRequired
isRequired :groupName="`${glassLocation}-${glassName}-${selectedTint}`"
:groupName="`${glassLocation}-${glassName}-${selectedTint}`" :validationRules="`${glassLocation}-${glassName}-part-required`"
validationRules="part-required" />
/>
</div>
</div> </div>
</div>
</buttonQuestion> </buttonQuestion>
</div> </div>
</div> </div>
@ -58,7 +57,8 @@ import { errorMessages } from "@/constants/error-messages";
// import { ErrorMessage } from "vee-validate"; // import { ErrorMessage } from "vee-validate";
defineRule("replace-options-required", required(errorMessages.OPTION_REQUIRED)); 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 { export default {
name: "glass-part-question", name: "glass-part-question",
@ -78,6 +78,7 @@ export default {
// validationRules: String, // validationRules: String,
}, },
mounted() { mounted() {
// this.setAllValidationRules();
this.LoadPreselectedValues(); this.LoadPreselectedValues();
}, },
components: { components: {
@ -108,15 +109,26 @@ export default {
return tintOptions; return tintOptions;
}, },
selectedPart: { selectedPartNumber: {
get: function () { get() {
return this.modelValue; console.log(this.modelValue)
return this.modelValue?.partNumber;
}, },
set: function (newValue) { set(newValue) {
this.$emit("update:modelValue", 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 // Creates a map of the feature list data in the correct Name/Value
// format for the button-question component. // format for the button-question component.
featureListData() { featureListData() {
@ -176,34 +188,47 @@ export default {
// Reset selections when tint changes for the same glass to ensure proper selection. // 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. // Also checks if only a single part is present for the tint.
ResetTintAndPartSelections() { ResetTintAndPartSelections() {
this.selectedTint = ""; console.log("Resetting!")
this.selectedPart = {}; // this.selectedTint = "";
this.selectedPartNumber = null;
this.AutoSelectIfSinglePart(); this.AutoSelectIfSinglePart();
}, },
// Check if only a single part is present for the tint and set the v-model if it is. // Check if only a single part is present for the tint and set the v-model if it is.
AutoSelectIfSinglePart() { AutoSelectIfSinglePart() {
// Check if the selected tint only has a single feature console.log("Autoselecting, my dear")
Object.keys(this.PartDataFromApi.partsOrQuestions ?? {}).forEach( console.log(this.PartDataFromApi.partsOrQuestions)
(key) => { console.log(this.glassName)
const currentGlassSelection = console.log(this.glassLocation)
this.PartDataFromApi.partsOrQuestions[key]; console.log(this.selectedTint)
console.log(this.partsForSelectedTint)
if ( if (this.partsForSelectedTint?.length == 1) {
currentGlassSelection.glassName === this.glassName && console.log("One!")
currentGlassSelection.glassLocation === this.selectedPartNumber = this.partsForSelectedTint[0].partNumber;
this.glassLocation console.log(this.selectedPartNumber)
) { }
if (currentGlassSelection.parts.length === 1) {
this.selectedPart = { // this.$nextTick()
[currentGlassSelection.glassLocation]: [ console.log(this.selectedPartNumber)
currentGlassSelection.parts[0].partNumber,
], // 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. // Loads the preselected values from the store.
@ -211,12 +236,10 @@ export default {
this.$nextTick(() => { this.$nextTick(() => {
if (this.modelValue !== undefined) { if (this.modelValue !== undefined) {
// Populate button-question model-value if parts data already exists in VueX // Populate button-question model-value if parts data already exists in VueX
const alreadyPopulatedPartsData = const alreadyPopulatedPartsData = this.$store.getters.lineItems.glassParts;
this.$store.getters.lineItems.glassParts;
Object.keys(alreadyPopulatedPartsData).forEach((key) => { Object.keys(alreadyPopulatedPartsData).forEach((key) => {
const partNumber = const partNumber = alreadyPopulatedPartsData[key].partNumber;
alreadyPopulatedPartsData[key].partNumber;
const tintColor = alreadyPopulatedPartsData[key].color; const tintColor = alreadyPopulatedPartsData[key].color;
Object.keys(this.modelValue).forEach((key) => { 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: { watch: {
selectedTint(newTint, previousTint) { selectedTint() {
this.selectedPart = null; console.log("watch me")
this.selectedPartNumber = null;
this.AutoSelectIfSinglePart()
} }
} }
}; };

View file

@ -21,12 +21,10 @@
</div> </div>
</div> </div>
</div> </div>
{{ glassParts }}
<div v-for="(item, i) in PartsForQuestions" :key="i"> <div v-for="(item, i) in PartsOrQuestions" :key="i">
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) --> <!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
<div class="container-fluid"> <hr v-if="i > 0" />
<hr v-if="i > 0" />
</div>
<glassPartQuestion <glassPartQuestion
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`" :ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
v-model="glassParts[item.glassLocation + '-' + item.glassName]" v-model="glassParts[item.glassLocation + '-' + item.glassName]"
@ -108,7 +106,7 @@ computed: {
isForwardActionDisabled() { isForwardActionDisabled() {
return !this.glassParts || Object.values(this.glassParts).filter(value => value).length === 0; return !this.glassParts || Object.values(this.glassParts).filter(value => value).length === 0;
}, },
PartsForQuestions() { PartsOrQuestions() {
const partsData = this.PartsFromApi; const partsData = this.PartsFromApi;
// Map API result data, to vehicle-parts data structure // Map API result data, to vehicle-parts data structure
@ -164,26 +162,35 @@ methods: {
// Match them to the parts from the API. // Match them to the parts from the API.
this.PartsFromApi.partsOrQuestions.forEach(part => { this.PartsFromApi.partsOrQuestions.forEach(part => {
const selectedPartNumberForGlassLocationAndName = this.glassParts[`${part.glassLocation}-${part.glassName}`]; const selectedPartForGlassLocationAndName = this.glassParts[`${part.glassLocation}-${part.glassName}`];
const selectedPartData = part.parts.filter(part => part.partNumber == selectedPartNumberForGlassLocationAndName); 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 no parts could be matched, throw an error.
if (matchedParts.length === 0) { if (matchedParts.length !== this.PartsFromApi.length) {
this.$refs.funnelFooter.removeLoader(); this.$refs.funnelFooter.removeLoader();
throw new Error("Could not match any parts to the selected parts"); throw new Error("Could not match any parts to the selected parts");
} }
this.$refs.funnelFooter.removeLoader();
// Save parts to the store. // Save parts to the store.
store.commit(storeMutations.UPDATE_GLASS_PARTS, matchedParts); store.commit(storeMutations.UPDATE_GLASS_PARTS, matchedParts);
// // Navigate to the next page. // Navigate to the next page.
// this.$router.navigateAfterSave( this.$router.navigateAfterSave(
// this.navigationScenarios.SELECTED_PARTS, this.navigationScenarios.SELECTED_PARTS,
// this.$route this.$route
// ); );
}, },
resetDependentState() { resetDependentState() {

View file

@ -1,7 +1,7 @@
<template> <template>
<div :class="'h-100 l' + colLength"> <div :class="{'h-100': !isWide}">
<div <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="[ :class="[
isWide ? 'horizontal' : '', isWide ? 'horizontal' : '',
(errors.length > 0 || hasError) ? 'has-error' : '', (errors.length > 0 || hasError) ? 'has-error' : '',
@ -25,7 +25,7 @@
tabindex="-1" tabindex="-1"
:for="buttonID" :for="buttonID"
:aria-labelledby="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" :class="getLabelClasses"
@mouseup="triggerButton()" @mouseup="triggerButton()"
> >

View file

@ -49,8 +49,8 @@ export default {
}, },
created() { created() {
if (this.selectedValues) { if (this.selectedValues) {
this.checkValue = this.selectedValues[0] === this.value; this.checkValue = this.selectedValues === this.value;
}else{ } else{
this.checkValue = false; this.checkValue = false;
} }
}, },
@ -86,12 +86,13 @@ export default {
}; };
</script> </script>
<style lang="scss" scoped>yu78zas <style lang="scss" scoped>
.form-check { .form-check {
.form-check-input { .form-check-input {
border: 1px solid $gray-500; border: 1px solid $gray-500;
border-radius: 100%; border-radius: 100%;
margin-right: 0.5rem; margin-right: 0.5rem;
margin-top: 0.12rem;
&:checked { &:checked {
background-color: $white; background-color: $white;
background-size: 71%; background-size: 71%;