diff --git a/src/constants/error-messages.js b/src/constants/error-messages.js new file mode 100644 index 000000000..ba2b0e585 --- /dev/null +++ b/src/constants/error-messages.js @@ -0,0 +1,12 @@ +const errorMessages = { + DAMAGE_LOCATION_REQUIRED: "Please select damage location", + DAMAGE_SIDE_REQUIRED: "Please select vehicle side", + DRIVER_SIDE_OPTIONS_REQUIRED: "Please select window", + PASSENGER_SIDE_OPTIONS_REQUIRED: "Please select window", + WINDSHIELD_DAMAGE_TYPE_REQUIRED: "Please select windshield damage", + WINDSHIELD_CHIP_COUNT_REQUIRED: "Please select chip(s)", + WINSHIELD_REPLACE_OPTIONS_REQUIRED: "Please select windshield part", + REPLACE_OPTIONS_REQUIRED: "Please select rear window type", +}; + +export { errorMessages }; \ No newline at end of file diff --git a/src/helpers/validation-rules.js b/src/helpers/validation-rules.js new file mode 100644 index 000000000..1ac4ce818 --- /dev/null +++ b/src/helpers/validation-rules.js @@ -0,0 +1,8 @@ +export function required(errorMessage) { + return (value) => { + if (!value || value.length < 1) { + return errorMessage; + } + return true; + }; +} \ No newline at end of file diff --git a/src/helpers/validation-rules.spec.js b/src/helpers/validation-rules.spec.js new file mode 100644 index 000000000..323e05ff1 --- /dev/null +++ b/src/helpers/validation-rules.spec.js @@ -0,0 +1,29 @@ +import { required } from "@/helpers/validation-rules"; + +describe("validation-rules.vue", () => { + test("required rules should return error if value missing", () => { + + //Arrange + const testFn = required("an error"); + + //Act + const testResponse = testFn(); + + //Assert + expect(testResponse).toBe("an error"); + }); +}); + +describe("validation-rules.vue", () => { + test("required rules should return true if value present", () => { + + //Arrange + const testFn = required("an error"); + + //Act + const testResponse = testFn('some value'); + + //Assert + expect(testResponse).toBe(true); + }); + }); \ No newline at end of file diff --git a/src/layouts/form-test/form-test.vue b/src/layouts/form-test/form-test.vue index 7f2c736b2..8e9aefe22 100644 --- a/src/layouts/form-test/form-test.vue +++ b/src/layouts/form-test/form-test.vue @@ -15,27 +15,38 @@ groupName="DamageLocationQuestion" /> + @@ -60,19 +71,23 @@ import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner"; import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header"; import replaceOptionsQuestion from "@/layouts/vehicle-damage/replace-options-question/replace-options-question"; import damageLocationQuestion from "@/layouts/vehicle-damage/damage-location-question/damage-location-question"; +import sideDoorOptions from "@/layouts/vehicle-damage/side-door-options/side-door-options"; import windshieldOptions from "@/layouts/vehicle-damage/windshield-options/windshield-options"; import alert from "@/ux-components/alert/alert"; -import { Form } from 'vee-validate'; - - // Supporting files import { fetchCmsContentForPage } from "@/helpers/cms-content-helper"; import { settleAllPromises } from "@/helpers/layout-helper"; import { storeActions } from "@/constants/store-actions"; import store from "@/store"; import baseMixin from "@/mixins/base-mixin"; +import { Form, defineRule } from "vee-validate"; +import { required } from "@/helpers/validation-rules"; +import { errorMessages } from "@/constants/error-messages"; +import { damageLocationsCms } from "@/constants/damage-locations-cms.js"; +// DEFINE VALIDATION RULES +defineRule("replace-options-required", required(errorMessages.REPLACE_OPTIONS_REQUIRED)); export default { name: "form-test", @@ -110,12 +125,19 @@ export default { vm.$refs.funnelSubHeader.initializeComponent( resultMap.cmsContent.FunnelSubHeaderWidget ); - vm.$refs.driverSideOptions.initializeComponent( - resultMap.cmsContent.DriverSideReplaceOptionsQuestion, resultMap.damageOptions.driverSideOptions.availableReplacementOptions - ); vm.$refs.damageLocation.initializeComponent( resultMap.cmsContent.DamageLocationQuestion, resultMap.damageOptions ); + vm.$refs.sideDoorOptions.initializeComponent( + resultMap.cmsContent.SideDoorSideQuestion, resultMap.cmsContent.DriverSideReplaceOptionsQuestion, resultMap.cmsContent.PassengerSideReplaceOptionsQuestion, resultMap.damageOptions.driverSideOptions.availableReplacementOptions, resultMap.damageOptions.passengerSideOptions.availableReplacementOptions + ); + vm.$refs.windshieldOptions.initializeComponent( + resultMap.cmsContent.WindshieldDamageTypeQuestion, resultMap.cmsContent.WindshieldChipCountQuestion, + resultMap.cmsContent.WindshieldReplaceOptionsQuestion, resultMap.damageOptions.windshieldOptions.availableReplacementOptions + ); + vm.$refs.backGlassOptions.initializeComponent( + resultMap.cmsContent.RearReplaceOptionsQuestion, resultMap.damageOptions.backGlassOptions.availableReplacementOptions + ); vm.$refs.funnelFooter.initializeComponent( resultMap.cmsContent.FunnelFooterWidget ); @@ -124,26 +146,20 @@ export default { data(){ return { selectedDamageLocations: [], - driverSideOptionsData: [], + sideDoorOptionsData: { + selectedDoorSides: [], + selectedDriverSideReplaceOptions: [], + selectedPassengerSideReplaceOptions: [] + }, + selectedWindshieldOptions: [], + selectedRearReplaceOptions: [], } }, - components: { - Form, - funnelHeader, - vehicleBanner, - funnelSubHeader, - damageLocationQuestion, - replaceOptionsQuestion, - funnelFooter, - windshieldOptions, - alert, - }, methods: { arePagePrerequisitesValid() { return store.getters.vehicle.carId !== null; }, resetDependentState() { - // Invokes store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES); }, onSubmit(values) { @@ -165,5 +181,64 @@ export default { } }, }, + computed: { + isWindshieldDamageLocation() { + return this.selectedDamageLocations.some(selectedDamages => + { + return selectedDamages.toUpperCase() === damageLocationsCms.WINDSHIELD; + }); + }, + isSideDoorDamageLocation() { + return this.selectedDamageLocations.some(selectedDamages => + { + return selectedDamages.toUpperCase() === damageLocationsCms.SIDEDOOR; + }); + }, + isRearWindowDamageLocation() { + return this.selectedDamageLocations.some(selectedDamages => + { + return selectedDamages.toUpperCase() === damageLocationsCms.REARWINDOW; + }); + }, + isWindshieldRepair() { + if (!this.isWindshieldDamageLocation) return false; + + return this.selectedWindshieldOptions.selectedWindshieldDamageType && this.selectedWindshieldOptions.selectedWindshieldDamageType.some(selectedDamageType => + { + return selectedDamageType.toUpperCase() === "REPAIR"; + }); + }, + isDriverSideReplace() { + if (!this.isSideDoorDamageLocation) return false; + + return this.sideDoorOptionsData.selectedDoorSides.some(selectedDriverSide => + { + return selectedDriverSide.toUpperCase() === damageLocationsCms.DRIVERSIDE; + }); + }, + isPassengerSideReplace() { + if (!this.isSideDoorDamageLocation) return false; + + return this.sideDoorOptionsData.selectedDoorSides.some(selectedPassengerSide => + { + return selectedPassengerSide.toUpperCase() === damageLocationsCms.PASSENGERSIDE; + }); + }, + hasRepairReplaceConflict() { + return this.isWindshieldDamageLocation && this.selectedDamageLocations.length > 1 && this.isWindshieldRepair; + }, + }, + components: { + funnelHeader, + funnelFooter, + vehicleBanner, + funnelSubHeader, + sideDoorOptions, + damageLocationQuestion, + windshieldOptions, + replaceOptionsQuestion, + Form, + alert, + }, }; diff --git a/src/layouts/vehicle-damage/damage-location-question/damage-location-question.vue b/src/layouts/vehicle-damage/damage-location-question/damage-location-question.vue index 89b3244e3..dff518342 100644 --- a/src/layouts/vehicle-damage/damage-location-question/damage-location-question.vue +++ b/src/layouts/vehicle-damage/damage-location-question/damage-location-question.vue @@ -9,7 +9,6 @@ v-model="selectedValues" validationRules="damage-location-required" /> - @@ -17,14 +16,11 @@ import buttonQuestion from "@/common-components/button-question/button-question"; import store from "@/store"; import { defineRule } from "vee-validate"; +import { required } from "@/helpers/validation-rules"; +import { errorMessages } from "@/constants/error-messages"; // DEFINE VALIDATION RULES -defineRule("damage-location-required", (value) => { - if (!value || value.length < 1) { - return "Please select damage location"; - } - return true; -}); +defineRule("damage-location-required", required(errorMessages.DAMAGE_LOCATION_REQUIRED)); export default ({ name: "damageLocationQuestion", diff --git a/src/layouts/vehicle-damage/replace-options-question/replace-options-question.vue b/src/layouts/vehicle-damage/replace-options-question/replace-options-question.vue index 25eca62da..cdbb0c48d 100644 --- a/src/layouts/vehicle-damage/replace-options-question/replace-options-question.vue +++ b/src/layouts/vehicle-damage/replace-options-question/replace-options-question.vue @@ -9,7 +9,7 @@ :groupName="groupName" buttonType="listCard" v-model="selectedValues" - validationRules="replace-options-required" + :validationRules="validationRules" /> @@ -18,15 +18,6 @@ diff --git a/src/layouts/vehicle-damage/windshield-options/windshield-chip-count-question/windshield-chip-count-question.vue b/src/layouts/vehicle-damage/windshield-options/windshield-chip-count-question/windshield-chip-count-question.vue index 3226d9656..c04832a92 100644 --- a/src/layouts/vehicle-damage/windshield-options/windshield-chip-count-question/windshield-chip-count-question.vue +++ b/src/layouts/vehicle-damage/windshield-options/windshield-chip-count-question/windshield-chip-count-question.vue @@ -8,6 +8,7 @@ buttonType="listButtonHorizontal" useTextForValue v-model="selectedChipCountValues" + :validationRules="validationRules" /> @@ -28,12 +29,19 @@ export default ({ modelValue: Array, groupName: String, isAvailable: Boolean, + validationRules: String, }, methods: { initializeComponent(cmsContent){ this.questionText = cmsContent.QuestionText; this.answersFromCms = cmsContent.Answers; - } + }, + updateSelectedValues() { + // UPDATE SELECTEDVALUES IF ONLY ONE ANSWER + if(Array.isArray(this.answersToDisplay) && this.answersToDisplay.length === 1 && this.selectedValues) { + this.selectedValues = [this.answersToDisplay[0].Name]; + } + }, }, computed: { selectedChipCountValues: { @@ -45,6 +53,12 @@ export default ({ } }, }, + watch: { + isAvailable(val) { + // CHECK TO UPDATE SELECTED VALUES WHEN ISAVAILABLE IS TRUE + val && this.updateSelectedValues(); + } + }, components: { buttonQuestion, } diff --git a/src/layouts/vehicle-damage/windshield-options/windshield-damage-type-question/windshield-damage-type-question.vue b/src/layouts/vehicle-damage/windshield-options/windshield-damage-type-question/windshield-damage-type-question.vue index 8031db546..4510b651c 100644 --- a/src/layouts/vehicle-damage/windshield-options/windshield-damage-type-question/windshield-damage-type-question.vue +++ b/src/layouts/vehicle-damage/windshield-options/windshield-damage-type-question/windshield-damage-type-question.vue @@ -7,6 +7,8 @@ :groupName="groupName" buttonType="listCard" v-model="selectedValues" + :suppressError="suppressError" + :validationRules="validationRules" /> @@ -14,24 +16,7 @@