CSR-343 Fix reloading/repopulating and CSS

This commit is contained in:
Katie 2022-06-28 17:46:05 -04:00
parent 06335ba625
commit 8fe1dd8d7b
6 changed files with 110 additions and 114 deletions

View file

@ -5,8 +5,8 @@
<span class="fs-5 fw-bold w-100">{{ questionText }}</span> <span class="fs-5 fw-bold w-100">{{ questionText }}</span>
</div> </div>
<div class="w-100 d-flex justify-content-center"> <div class="w-100 d-flex justify-content-center">
<fieldset class="w-100" :aria-required=isRequired :class="getFieldSetClasses" :role="isMultiSelect ? 'group' : 'radiogroup'" :aria-labelledby="groupName"> <fieldset class="w-100" :aria-required=isRequired :class="getFieldSetClasses" :role="isMultiSelect ? 'group' : 'radiogroup'" :aria-labelledby="formattedGroupName">
<legend class="sr-only" :data-focus-target="groupName" :id="groupName" tabindex="-1"> <legend class="sr-only" :data-focus-target="formattedGroupName" :id="formattedGroupName" 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="getComponentLoopWrapperClasses"> <div :class="getComponentLoopWrapperClasses">
@ -14,13 +14,13 @@
<component <component
:is="buttonType" :is="buttonType"
@isCheckedChanged="handleCheckedChanged" @isCheckedChanged="handleCheckedChanged"
:buttonID="answer.Name ? groupName + '-' + answer.Name : groupName + '-' + answer" :buttonID="answer.Name ? formattedGroupName + '-' + answer.Name : formattedGroupName + '-' + answer"
:value="getValues(answer)" :value="getValues(answer)"
:buttonLabel="answer.Text ? answer.Text : answer" :buttonLabel="answer.Text ? answer.Text : answer"
:buttonLabelSubCopy="answer.SubText" :buttonLabelSubCopy="answer.SubText"
:textPosition="textPosition" :textPosition="textPosition"
:isMultiSelect="isMultiSelect" :isMultiSelect="isMultiSelect"
:groupName="groupName" :groupName="formattedGroupName"
:selectingInitiatesLoad="selectingInitiatesLoad" :selectingInitiatesLoad="selectingInitiatesLoad"
:loaderColor="loaderColor" :loaderColor="loaderColor"
:loaderPosition="loaderPosition" :loaderPosition="loaderPosition"
@ -48,7 +48,7 @@
</fieldset> </fieldset>
</div> </div>
<div class="row form-test-error mt-1"> <div class="row form-test-error mt-1">
<error-message :name="groupName" v-if="!suppressError"></error-message> <error-message :name="formattedGroupName" v-if="!suppressError"></error-message>
</div> </div>
</div> </div>
</template> </template>
@ -97,6 +97,9 @@ export default {
}, },
}, },
computed: { computed: {
formattedGroupName() {
return this.groupName.replace(" ", "-");
},
getFieldSetClasses() { getFieldSetClasses() {
if (this.isOverflowScrollable) { if (this.isOverflowScrollable) {
return "container-fluid overflow-scroll position-absolute px-5 pt-1 py-0"; return "container-fluid overflow-scroll position-absolute px-5 pt-1 py-0";
@ -175,6 +178,7 @@ export default {
} }
} }
this.$emit("change");
this.$emit("isCheckedChanged", val); this.$emit("isCheckedChanged", val);
}, },
}, },

View file

@ -14,7 +14,7 @@
isRequired isRequired
:groupName="`${glassLocation}-${glassName}`" :groupName="`${glassLocation}-${glassName}`"
@isCheckedChanged="ResetTintAndPartSelections" @isCheckedChanged="ResetTintAndPartSelections"
validationRules="replace-options-required" :validationRules="`${glassLocation}-${glassName}-tint-required`"
> >
<div class="row my-2" aria-live="polite"> <div class="row my-2" aria-live="polite">
<div class="col"> <div class="col">
@ -36,12 +36,6 @@
</div> </div>
</div> </div>
</div> </div>
<div class="row form-test-error mt-1">
<!-- <error-message
:name="`${glassLocation}-${glassName}`"
v-if="!suppressError"
></error-message> -->
</div>
</template> </template>
<script> <script>
@ -54,11 +48,6 @@ import { getCustomTransformValue } from "@/constants/dynamictext-mapper";
import { defineRule } from "vee-validate"; import { defineRule } from "vee-validate";
import { required } from "@/helpers/validation-rules"; import { required } from "@/helpers/validation-rules";
import { errorMessages } from "@/constants/error-messages"; 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(`${this.glassLocation}-${this.glassName}-part-required`, required(errorMessages.OPTION_REQUIRED));
export default { export default {
name: "glass-part-question", name: "glass-part-question",
@ -75,15 +64,14 @@ export default {
glassLocation: String, glassLocation: String,
colorAnswers: Array, colorAnswers: Array,
modelValue: Object, modelValue: Object,
// validationRules: String, alreadyPopulatedPartsData: Object
}, },
mounted() { mounted() {
// this.setAllValidationRules(); this.setAllValidationRules();
this.LoadPreselectedValues(); this.LoadPreselectedValues();
}, },
components: { components: {
buttonQuestion, buttonQuestion,
// ErrorMessage,
}, },
computed: { computed: {
colorQuestionText() { colorQuestionText() {
@ -111,13 +99,9 @@ export default {
selectedPartNumber: { selectedPartNumber: {
get() { get() {
console.log(this.modelValue)
return this.modelValue?.partNumber; return this.modelValue?.partNumber;
}, },
set(newValue) { set(newValue) {
console.log("setting")
console.log(newValue)
this.$emit("update:modelValue", this.partsForSelectedTint.filter(part => part.partNumber == newValue)[0]); this.$emit("update:modelValue", this.partsForSelectedTint.filter(part => part.partNumber == newValue)[0]);
}, },
}, },
@ -188,47 +172,15 @@ 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() {
console.log("Resetting!")
// this.selectedTint = "";
this.selectedPartNumber = null; 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() {
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 (this.partsForSelectedTint?.length == 1) { if (this.partsForSelectedTint?.length == 1) {
console.log("One!")
this.selectedPartNumber = this.partsForSelectedTint[0].partNumber; 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. // Loads the preselected values from the store.
@ -236,40 +188,18 @@ 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 = this.$store.getters.lineItems.glassParts; this.selectedTint = this.alreadyPopulatedPartsData.filter(part => part.partNumber === this.selectedPartNumber)[0].color;
Object.keys(alreadyPopulatedPartsData).forEach((key) => {
const partNumber = alreadyPopulatedPartsData[key].partNumber;
const tintColor = alreadyPopulatedPartsData[key].color;
Object.keys(this.modelValue).forEach((key) => {
if (this.modelValue[key][0] === partNumber) {
this.selectedTint = tintColor;
// this.selectedTint[tintColor] = {
// buttonId: `${this.glassLocation}-${this.glassName}-${tintColor}`,
// checkValue: "",
// value: `${this.glassLocation}-${this.glassName}-${tintColor}`,
// };
}
});
});
} }
}); });
}, },
// setAllValidationRules() { setAllValidationRules() {
// console.log("SETTING VALIDATION RULES") defineRule(`${this.glassLocation}-${this.glassName}-tint-required`, required(errorMessages.OPTION_REQUIRED));
// console.log(this.PartDataFromApi.partsOrQuestions) defineRule(`${this.glassLocation}-${this.glassName}-part-required`, required(errorMessages.OPTION_REQUIRED));
// 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() { selectedTint() {
console.log("watch me") this.AutoSelectIfSinglePart();
this.selectedPartNumber = null;
this.AutoSelectIfSinglePart()
} }
} }
}; };

View file

@ -31,6 +31,7 @@
:glassLocation="item.glassLocation" :glassLocation="item.glassLocation"
:glassName="item.glassName" :glassName="item.glassName"
:colorAnswers="item.colorAnswers" :colorAnswers="item.colorAnswers"
:alreadyPopulatedPartsData="alreadyPopulatedPartsData"
/> />
</div> </div>
<funnelFooter <funnelFooter
@ -91,6 +92,7 @@ data() {
return { return {
glassParts: {}, glassParts: {},
alertWidgetData: Object, alertWidgetData: Object,
alreadyPopulatedPartsData: {}
}; };
}, },
components: { components: {
@ -163,34 +165,28 @@ 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 selectedPartForGlassLocationAndName = this.glassParts[`${part.glassLocation}-${part.glassName}`]; 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]; const selectedPartData = part.parts.filter(part => selectedPartForGlassLocationAndName && part.partNumber == selectedPartForGlassLocationAndName?.partNumber)[0];
if (selectedPartData) if (selectedPartData)
matchedParts.push(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 !== this.PartsFromApi.length) { if (Object.keys(matchedParts).length !== this.PartsFromApi.partsOrQuestions.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(); console.log(matchedParts)
// 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() {
@ -198,21 +194,48 @@ methods: {
}, },
LoadInitialPartsData() { LoadInitialPartsData() {
const partsData = this.PartsFromApi; console.log("Loading in vehicle-parts")
const alreadyPopulatedPartsData = this.$store.getters.lineItems.glassParts === null ? {} : this.$store.getters.lineItems.glassParts; this.alreadyPopulatedPartsData = this.$store.getters.lineItems.glassParts ?? [];
// MOCKKKK, real one is above
// console.log(this.PartsFromApi.partsOrQuestions[0])
// this.alreadyPopulatedPartsData = [this.PartsFromApi.partsOrQuestions[0].parts[0], this.PartsFromApi.partsOrQuestions[1].parts[0], this.PartsFromApi.partsOrQuestions[2].parts[0], this.PartsFromApi.partsOrQuestions[3].parts[0], this.PartsFromApi.partsOrQuestions[4].parts[0]];
// console.log("MOCK alreadyPopulatedPartsData")
// console.log(this.alreadyPopulatedPartsData)
const savedPartNumbers = this.alreadyPopulatedPartsData.map(part => part.partNumber)
console.log(savedPartNumbers)
// const allPartsForGlass = this.PartsFromApi.partsOrQuestions.filter(glass => glass.glassLocation == this.glassLocation && glass.glassName == this.glassName)[0].parts;
partsData.partsOrQuestions.map((g) => { this.PartsFromApi.partsOrQuestions.forEach(glass => {
console.log("glass")
console.log(glass)
const savedPart = glass.parts.filter(part => savedPartNumbers.includes(part.partNumber))[0];
console.log('savedPart')
console.log(savedPart)
if (savedPart) {
this.glassParts[`${glass.glassLocation}-${glass.glassName}`.replace(" ", "-")] = savedPart;
}
console.log('glassParts')
console.log(this.glassParts)
// this.glassParts[`${glass.glassLocation}-${glass.glassName}`] =
// If the part is already populated, use the value from the store and populate the v-model. // If the part is already populated, use the value from the store and populate the v-model.
Object.keys(alreadyPopulatedPartsData).forEach((key) => {
const partNumber = alreadyPopulatedPartsData[key].partNumber; // Object.keys(alreadyPopulatedPartsData).forEach(savedPart => {
g.parts.forEach((p) => { // const savedPartNumber = savedPart.partNumber;
if (p.partNumber === partNumber) {
this.glassParts[g.glassLocation + "-" + g.glassName] = { // let test = partFromApi.parts.filter(part => part.partNumber == savedPartNumber);
[g.glassLocation]: [partNumber], // console.log(test);
}; // // g.parts.forEach((p) => {
} // // if (p.partNumber === partNumber) {
}); // // this.glassParts[g.glassLocation + "-" + g.glassName] = {
}); // // [g.glassLocation]: [partNumber],
// // };
// // }
// // });
// });
}); });
}, },
}, },

View file

@ -12,6 +12,7 @@ const fmgPageValues = {
REVEAL: "reveal", REVEAL: "reveal",
ESTIMATE: "estimate", ESTIMATE: "estimate",
ADDRESS_VEHICLES: "address-vehicles", ADDRESS_VEHICLES: "address-vehicles",
QUOTE: "quote"
}; };
export { fmgPageValues }; export { fmgPageValues };

View file

@ -3,6 +3,7 @@
<div <div
class="list-card w-100 rounded-3 d-flex align-items-center" class="list-card w-100 rounded-3 d-flex align-items-center"
:class="[ :class="[
'h-100',
isWide ? 'horizontal' : '', isWide ? 'horizontal' : '',
(errors.length > 0 || hasError) ? 'has-error' : '', (errors.length > 0 || hasError) ? 'has-error' : '',
]" ]"
@ -19,15 +20,16 @@
:value="value" :value="value"
:aria-required="isRequired" :aria-required="isRequired"
v-model="checkValue" v-model="checkValue"
@change="handleInputChange()" :checked="checkValue"
@change="handleInputChange"
/> />
<label <label
tabindex="-1" tabindex="-1"
:for="buttonID" :for="buttonID"
:aria-labelledby="buttonID" :aria-labelledby="buttonID"
class="d-flex w-100 align-items-center px-2" class="d-flex w-100 align-items-center px-2 h-100"
:class="getLabelClasses" :class="getLabelClasses"
@mouseup="triggerButton()" @mouseup="triggerButton"
> >
<img <img
:id="buttonImageId" :id="buttonImageId"
@ -102,6 +104,12 @@ export default {
? this.selectedValues.includes(this.value) ? this.selectedValues.includes(this.value)
: this.selectedValues[0]; : this.selectedValues[0];
} }
else {
console.log("HI")
console.log(this.modelValue)
console.log(this.value)
this.checkValue = this.selectedValues == this.value || this.modelValue == this.value;
}
}, },
unmounted() { // needed to clear this button's selectedValues if it is removed to keep validation in sync unmounted() { // needed to clear this button's selectedValues if it is removed to keep validation in sync
if (this.clearOnUnmount) { if (this.clearOnUnmount) {
@ -124,7 +132,9 @@ export default {
}, },
methods: { methods: {
handleInputChange() { handleInputChange() {
console.log("HI 1")
if(!this.selectingInitiatesLoad) { if(!this.selectingInitiatesLoad) {
console.log("HI 2")
this.handleCheckChange(); this.handleCheckChange();
} }
}, },
@ -164,6 +174,22 @@ export default {
this.checkValue = newVal.value; this.checkValue = newVal.value;
} }
}, },
selectedValues(newVal) {
// this.handleChange(newVal == this.value);
console.log("WATCH")
console.log(newVal)
console.log(typeof newVal)
console.log(typeof newVal === "string")
if (typeof newVal === "string") {
console.log(this.value)
// console.log(newVal == this.value)
this.handleChange(this.value);
this.checkValue = newVal == this.value;
}
else if (newVal !== undefined) {
this.checkValue = newVal.value;
}
},
}, },
setup(props) { setup(props) {
const inputType = props.isMultiSelect ? "checkbox" : "radio"; const inputType = props.isMultiSelect ? "checkbox" : "radio";

View file

@ -50,6 +50,7 @@ export default {
created() { created() {
if (this.selectedValues) { if (this.selectedValues) {
this.checkValue = this.selectedValues === this.value; this.checkValue = this.selectedValues === this.value;
this.handleCheckChange();
} else{ } else{
this.checkValue = false; this.checkValue = false;
} }
@ -88,14 +89,17 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.form-check { .form-check {
position: relative;
.form-check-input { .form-check-input {
border: 1px solid $gray-500; border: 1px solid $gray-500;
border-radius: 100%; border-radius: 50%;
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%;
background-position: center;
border: 1px solid $blue; border: 1px solid $blue;
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50' xml:space='preserve'%3e%3ccircle cx='25' cy='25' r='25' fill='%231574A1'/%3e%3c/svg%3e"); background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 50 50' xml:space='preserve'%3e%3ccircle cx='25' cy='25' r='25' fill='%231574A1'/%3e%3c/svg%3e");
+ label { + label {
@ -109,7 +113,15 @@ export default {
&:focus { &:focus {
box-shadow: 0 0 0 2.5px $blue; box-shadow: 0 0 0 2.5px $blue;
} }
&, & + label {
margin-top: 0;
position: absolute;
top: 50%;
transform: translateY(-50%);
}
} }
&:hover { &:hover {
.form-check-input { .form-check-input {
box-shadow: 0 0 0 4px $blue-300; box-shadow: 0 0 0 4px $blue-300;