Merge branch 'develop' into feature/CSR-319
|
|
@ -17,6 +17,9 @@ module.exports = {
|
||||||
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
|
"!src/layouts/vehicle-damage/windshield-options/windshield-options.vue",
|
||||||
"!src/layouts/address-poc/address-poc.vue",
|
"!src/layouts/address-poc/address-poc.vue",
|
||||||
"!src/layouts/nested-radio-poc/nested-radio.vue",
|
"!src/layouts/nested-radio-poc/nested-radio.vue",
|
||||||
|
"!src/layouts/button-question-examples/**/*.vue",
|
||||||
|
"!src/layouts/part-questions/**/*.vue",
|
||||||
|
"!src/layouts/reveal/**/*.vue",
|
||||||
], //! means exclude from coverage.
|
], //! means exclude from coverage.
|
||||||
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
testMatch: ["**/*.spec.(js|jsx|ts|tsx)|**/__tests__/*.(js|jsx|ts|tsx)"],
|
||||||
coverageThreshold: {
|
coverageThreshold: {
|
||||||
|
|
|
||||||
18
src/assets/img/tints/Glass-BlueShade-BlueTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8976)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8976" x1="51.9586" y1="33.0102" x2="51.9586" y2="6.98049" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CADCDD"/>
|
||||||
|
<stop offset="0.2653" stop-color="#C8DBDC"/>
|
||||||
|
<stop offset="0.3972" stop-color="#C0D6D7"/>
|
||||||
|
<stop offset="0.4996" stop-color="#B3CDD0"/>
|
||||||
|
<stop offset="0.5869" stop-color="#A0C1C5"/>
|
||||||
|
<stop offset="0.6645" stop-color="#88B1B8"/>
|
||||||
|
<stop offset="0.7353" stop-color="#6A9EA7"/>
|
||||||
|
<stop offset="0.8009" stop-color="#468793"/>
|
||||||
|
<stop offset="0.8607" stop-color="#1E6D7C"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
18
src/assets/img/tints/Glass-BlueShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_9006)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_9006" x1="51.9586" y1="33.0065" x2="51.9586" y2="6.97682" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#D0CDC2"/>
|
||||||
|
<stop offset="0.2632" stop-color="#CECCC1"/>
|
||||||
|
<stop offset="0.394" stop-color="#C6C8BE"/>
|
||||||
|
<stop offset="0.4956" stop-color="#B9C0B8"/>
|
||||||
|
<stop offset="0.5823" stop-color="#A6B6B1"/>
|
||||||
|
<stop offset="0.6593" stop-color="#8EA8A6"/>
|
||||||
|
<stop offset="0.7295" stop-color="#70989A"/>
|
||||||
|
<stop offset="0.7947" stop-color="#4C848B"/>
|
||||||
|
<stop offset="0.854" stop-color="#246E7A"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
19
src/assets/img/tints/Glass-BlueShade-GrayTint.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8763)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8763" x1="51.9586" y1="33.0065" x2="51.9586" y2="6.97682" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#E7E7E8"/>
|
||||||
|
<stop offset="0.2559" stop-color="#E5E6E7"/>
|
||||||
|
<stop offset="0.383" stop-color="#DDE1E3"/>
|
||||||
|
<stop offset="0.4818" stop-color="#D0D9DC"/>
|
||||||
|
<stop offset="0.5659" stop-color="#BDCDD1"/>
|
||||||
|
<stop offset="0.6409" stop-color="#A5BFC4"/>
|
||||||
|
<stop offset="0.7091" stop-color="#87ACB4"/>
|
||||||
|
<stop offset="0.7724" stop-color="#6397A1"/>
|
||||||
|
<stop offset="0.8318" stop-color="#3A7D8A"/>
|
||||||
|
<stop offset="0.8859" stop-color="#0C6272"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
18
src/assets/img/tints/Glass-BlueShade-GreenTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8750)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8750" x1="51.9586" y1="33.0219" x2="51.9586" y2="6.99218" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CBE9DD"/>
|
||||||
|
<stop offset="0.265" stop-color="#C9E7DC"/>
|
||||||
|
<stop offset="0.3966" stop-color="#C1E2D7"/>
|
||||||
|
<stop offset="0.4989" stop-color="#B4D9D0"/>
|
||||||
|
<stop offset="0.5861" stop-color="#A1CCC6"/>
|
||||||
|
<stop offset="0.6636" stop-color="#89BAB8"/>
|
||||||
|
<stop offset="0.7343" stop-color="#6BA5A7"/>
|
||||||
|
<stop offset="0.7998" stop-color="#478C93"/>
|
||||||
|
<stop offset="0.8595" stop-color="#1F707D"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
19
src/assets/img/tints/Glass-BlueShade-NoTint.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8908)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8908" x1="51.9812" y1="33.0046" x2="51.9812" y2="6.97492" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="white"/>
|
||||||
|
<stop offset="0.2491" stop-color="#FDFEFE"/>
|
||||||
|
<stop offset="0.3729" stop-color="#F5F9F9"/>
|
||||||
|
<stop offset="0.4691" stop-color="#E8F0F2"/>
|
||||||
|
<stop offset="0.551" stop-color="#D5E4E7"/>
|
||||||
|
<stop offset="0.6239" stop-color="#BDD4D9"/>
|
||||||
|
<stop offset="0.6904" stop-color="#9FC1C7"/>
|
||||||
|
<stop offset="0.752" stop-color="#7BAAB3"/>
|
||||||
|
<stop offset="0.8099" stop-color="#528F9A"/>
|
||||||
|
<stop offset="0.8626" stop-color="#247280"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
18
src/assets/img/tints/Glass-BrownShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8984)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8984" x1="51.9519" y1="33.0065" x2="51.9519" y2="6.97682" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#D0CDC2"/>
|
||||||
|
<stop offset="0.2738" stop-color="#CECBC0"/>
|
||||||
|
<stop offset="0.4097" stop-color="#C9C6B8"/>
|
||||||
|
<stop offset="0.5154" stop-color="#C0BCAB"/>
|
||||||
|
<stop offset="0.6055" stop-color="#B3AD98"/>
|
||||||
|
<stop offset="0.6856" stop-color="#A39B80"/>
|
||||||
|
<stop offset="0.7586" stop-color="#8E8462"/>
|
||||||
|
<stop offset="0.8262" stop-color="#766A3E"/>
|
||||||
|
<stop offset="0.8879" stop-color="#5B4B16"/>
|
||||||
|
<stop offset="0.8993" stop-color="#55450E"/>
|
||||||
|
<stop offset="1" stop-color="#55450E"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
17
src/assets/img/tints/Glass-GrayShade-BlueTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8980)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8980" x1="51.9552" y1="33.0102" x2="51.9552" y2="6.98049" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CADCDD"/>
|
||||||
|
<stop offset="0.2908" stop-color="#C8DADB"/>
|
||||||
|
<stop offset="0.4353" stop-color="#C1D2D3"/>
|
||||||
|
<stop offset="0.5475" stop-color="#B6C5C6"/>
|
||||||
|
<stop offset="0.6432" stop-color="#A5B2B3"/>
|
||||||
|
<stop offset="0.7282" stop-color="#909A9B"/>
|
||||||
|
<stop offset="0.8057" stop-color="#767C7D"/>
|
||||||
|
<stop offset="0.8761" stop-color="#58595A"/>
|
||||||
|
<stop offset="0.8993" stop-color="#4C4C4D"/>
|
||||||
|
<stop offset="1" stop-color="#4C4C4D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 981 B |
17
src/assets/img/tints/Glass-GrayShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_9018)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_9018" x1="51.9552" y1="33.0065" x2="51.9552" y2="6.97682" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#D0CDC2"/>
|
||||||
|
<stop offset="0.2978" stop-color="#CECBC0"/>
|
||||||
|
<stop offset="0.4457" stop-color="#C6C3B9"/>
|
||||||
|
<stop offset="0.5606" stop-color="#B9B6AE"/>
|
||||||
|
<stop offset="0.6585" stop-color="#A6A49D"/>
|
||||||
|
<stop offset="0.7456" stop-color="#8E8C87"/>
|
||||||
|
<stop offset="0.8237" stop-color="#71706D"/>
|
||||||
|
<stop offset="0.8959" stop-color="#4E4E4F"/>
|
||||||
|
<stop offset="0.8993" stop-color="#4C4C4D"/>
|
||||||
|
<stop offset="1" stop-color="#4C4C4D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 981 B |
17
src/assets/img/tints/Glass-GrayShade-GrayTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8978)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8978" x1="51.9552" y1="33.0065" x2="51.9552" y2="6.97682" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#E7E7E8"/>
|
||||||
|
<stop offset="0.2851" stop-color="#E5E5E6"/>
|
||||||
|
<stop offset="0.4267" stop-color="#DDDDDE"/>
|
||||||
|
<stop offset="0.5368" stop-color="#D0D0D1"/>
|
||||||
|
<stop offset="0.6305" stop-color="#BDBDBE"/>
|
||||||
|
<stop offset="0.7139" stop-color="#A5A5A6"/>
|
||||||
|
<stop offset="0.7899" stop-color="#878788"/>
|
||||||
|
<stop offset="0.8589" stop-color="#646465"/>
|
||||||
|
<stop offset="0.8993" stop-color="#4C4C4D"/>
|
||||||
|
<stop offset="1" stop-color="#4C4C4D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 981 B |
17
src/assets/img/tints/Glass-GrayShade-GreenTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8932)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8932" x1="51.9552" y1="33.0219" x2="51.9552" y2="6.99218" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CBE9DD"/>
|
||||||
|
<stop offset="0.2841" stop-color="#C9E7DB"/>
|
||||||
|
<stop offset="0.4252" stop-color="#C3DFD4"/>
|
||||||
|
<stop offset="0.5349" stop-color="#B8D2C8"/>
|
||||||
|
<stop offset="0.6283" stop-color="#A9BFB7"/>
|
||||||
|
<stop offset="0.7114" stop-color="#96A7A0"/>
|
||||||
|
<stop offset="0.7871" stop-color="#7D8985"/>
|
||||||
|
<stop offset="0.8559" stop-color="#616665"/>
|
||||||
|
<stop offset="0.8993" stop-color="#4C4C4D"/>
|
||||||
|
<stop offset="1" stop-color="#4C4C4D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 981 B |
20
src/assets/img/tints/Glass-GreenShade-BlueTint.svg
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="#CEE7DB"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8920)"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8920" x1="51.9618" y1="33.0102" x2="51.9618" y2="6.98049" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CADCDD"/>
|
||||||
|
<stop offset="0.2653" stop-color="#C8DBDB"/>
|
||||||
|
<stop offset="0.3972" stop-color="#C0D6D5"/>
|
||||||
|
<stop offset="0.4996" stop-color="#B3CFCB"/>
|
||||||
|
<stop offset="0.5869" stop-color="#A0C4BD"/>
|
||||||
|
<stop offset="0.6645" stop-color="#88B6AA"/>
|
||||||
|
<stop offset="0.7353" stop-color="#6AA593"/>
|
||||||
|
<stop offset="0.8009" stop-color="#469177"/>
|
||||||
|
<stop offset="0.8607" stop-color="#1E7A58"/>
|
||||||
|
<stop offset="0.8993" stop-color="#006941"/>
|
||||||
|
<stop offset="1" stop-color="#006941"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
18
src/assets/img/tints/Glass-GreenShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8982)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8982" x1="51.9814" y1="33.0065" x2="51.9814" y2="6.97682" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#D0CDC2"/>
|
||||||
|
<stop offset="0.2632" stop-color="#CECCC1"/>
|
||||||
|
<stop offset="0.394" stop-color="#C6C8BC"/>
|
||||||
|
<stop offset="0.4956" stop-color="#B9C2B4"/>
|
||||||
|
<stop offset="0.5823" stop-color="#A6B9A8"/>
|
||||||
|
<stop offset="0.6593" stop-color="#8EAD99"/>
|
||||||
|
<stop offset="0.7295" stop-color="#709F86"/>
|
||||||
|
<stop offset="0.7947" stop-color="#4C8E70"/>
|
||||||
|
<stop offset="0.854" stop-color="#247A57"/>
|
||||||
|
<stop offset="0.8993" stop-color="#006941"/>
|
||||||
|
<stop offset="1" stop-color="#006941"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
18
src/assets/img/tints/Glass-GreenShade-GreenTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="url(#paint0_linear_841_8896)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8896" x1="51.9618" y1="33.0219" x2="51.9618" y2="6.99218" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CBE9DD"/>
|
||||||
|
<stop offset="0.265" stop-color="#C9E8DB"/>
|
||||||
|
<stop offset="0.3966" stop-color="#C1E3D5"/>
|
||||||
|
<stop offset="0.4989" stop-color="#B4DACB"/>
|
||||||
|
<stop offset="0.5861" stop-color="#A1CFBD"/>
|
||||||
|
<stop offset="0.6636" stop-color="#89BFAA"/>
|
||||||
|
<stop offset="0.7343" stop-color="#6BAC93"/>
|
||||||
|
<stop offset="0.7998" stop-color="#479678"/>
|
||||||
|
<stop offset="0.8595" stop-color="#1F7D59"/>
|
||||||
|
<stop offset="0.8993" stop-color="#006941"/>
|
||||||
|
<stop offset="1" stop-color="#006941"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1 KiB |
3
src/assets/img/tints/Glass-NoShade-BlueTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="#CBDDDE" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 370 B |
3
src/assets/img/tints/Glass-NoShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="#D1CEC3" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 370 B |
3
src/assets/img/tints/Glass-NoShade-DarkBrownTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="#5D564C" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 370 B |
3
src/assets/img/tints/Glass-NoShade-DaryGrayTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="#D3D3D3" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 370 B |
3
src/assets/img/tints/Glass-NoShade-GrayTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="#E9E9EB" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 370 B |
3
src/assets/img/tints/Glass-NoShade-GreenTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="#CBE9DD" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 370 B |
3
src/assets/img/tints/Glass-NoShade-NoTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="white" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 368 B |
3
src/assets/img/tints/Glass-NoShade-Privacy.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M78.25 33H25.7083C24.2188 33 23 31.7812 23 30.2917V9.70833C23 8.21874 24.2188 7 25.7083 7H78.25C79.7396 7 80.9583 8.21874 80.9583 9.70833V30.2917C80.9583 31.7812 79.7396 33 78.25 33Z" fill="#626167" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 370 B |
18
src/assets/img/tints/Windshield-BlueShade-BlueTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8966)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8966" x1="51.9716" y1="34.0522" x2="51.9716" y2="5.97896" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CADCDD"/>
|
||||||
|
<stop offset="0.2653" stop-color="#C8DBDC"/>
|
||||||
|
<stop offset="0.3972" stop-color="#C0D6D7"/>
|
||||||
|
<stop offset="0.4996" stop-color="#B3CDD0"/>
|
||||||
|
<stop offset="0.5869" stop-color="#A0C1C5"/>
|
||||||
|
<stop offset="0.6645" stop-color="#88B1B8"/>
|
||||||
|
<stop offset="0.7353" stop-color="#6A9EA7"/>
|
||||||
|
<stop offset="0.8009" stop-color="#468793"/>
|
||||||
|
<stop offset="0.8607" stop-color="#1E6D7C"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
18
src/assets/img/tints/Windshield-BlueShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_9004)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_9004" x1="51.9716" y1="34.0483" x2="51.9716" y2="5.975" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#D0CDC2"/>
|
||||||
|
<stop offset="0.2632" stop-color="#CECCC1"/>
|
||||||
|
<stop offset="0.394" stop-color="#C6C8BE"/>
|
||||||
|
<stop offset="0.4956" stop-color="#B9C0B8"/>
|
||||||
|
<stop offset="0.5823" stop-color="#A6B6B1"/>
|
||||||
|
<stop offset="0.6593" stop-color="#8EA8A6"/>
|
||||||
|
<stop offset="0.7295" stop-color="#70989A"/>
|
||||||
|
<stop offset="0.7947" stop-color="#4C848B"/>
|
||||||
|
<stop offset="0.854" stop-color="#246E7A"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
19
src/assets/img/tints/Windshield-BlueShade-GrayTint.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_825_8758)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_825_8758" x1="51.9716" y1="34.0483" x2="51.9716" y2="5.975" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#E7E7E8"/>
|
||||||
|
<stop offset="0.2559" stop-color="#E5E6E7"/>
|
||||||
|
<stop offset="0.383" stop-color="#DDE1E3"/>
|
||||||
|
<stop offset="0.4818" stop-color="#D0D9DC"/>
|
||||||
|
<stop offset="0.5659" stop-color="#BDCDD1"/>
|
||||||
|
<stop offset="0.6409" stop-color="#A5BFC4"/>
|
||||||
|
<stop offset="0.7091" stop-color="#87ACB4"/>
|
||||||
|
<stop offset="0.7724" stop-color="#6397A1"/>
|
||||||
|
<stop offset="0.8318" stop-color="#3A7D8A"/>
|
||||||
|
<stop offset="0.8859" stop-color="#0C6272"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
17
src/assets/img/tints/Windshield-BlueShade-GreenTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path opacity="0.99" fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_206_8118)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_206_8118" x1="51.9712" y1="34.0648" x2="51.9712" y2="5.99159" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CEDEE7"/>
|
||||||
|
<stop offset="0.265" stop-color="#C9E7DC"/>
|
||||||
|
<stop offset="0.3966" stop-color="#C1E2D7"/>
|
||||||
|
<stop offset="0.4989" stop-color="#B4D9D0"/>
|
||||||
|
<stop offset="0.5861" stop-color="#A1CCC6"/>
|
||||||
|
<stop offset="0.6636" stop-color="#89BAB8"/>
|
||||||
|
<stop offset="0.7343" stop-color="#6BA5A7"/>
|
||||||
|
<stop offset="0.7998" stop-color="#478C93"/>
|
||||||
|
<stop offset="0.8993" stop-color="#125B7E"/>
|
||||||
|
<stop offset="1" stop-color="#125B7E"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
19
src/assets/img/tints/Windshield-BlueShade-NoTint.svg
Normal file
|
|
@ -0,0 +1,19 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8906)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8906" x1="52.0028" y1="34.0462" x2="52.0028" y2="5.97295" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="white"/>
|
||||||
|
<stop offset="0.2491" stop-color="#FDFEFE"/>
|
||||||
|
<stop offset="0.3729" stop-color="#F5F9F9"/>
|
||||||
|
<stop offset="0.4691" stop-color="#E8F0F2"/>
|
||||||
|
<stop offset="0.551" stop-color="#D5E4E7"/>
|
||||||
|
<stop offset="0.6239" stop-color="#BDD4D9"/>
|
||||||
|
<stop offset="0.6904" stop-color="#9FC1C7"/>
|
||||||
|
<stop offset="0.752" stop-color="#7BAAB3"/>
|
||||||
|
<stop offset="0.8099" stop-color="#528F9A"/>
|
||||||
|
<stop offset="0.8626" stop-color="#247280"/>
|
||||||
|
<stop offset="0.8993" stop-color="#005A6B"/>
|
||||||
|
<stop offset="1" stop-color="#005A6B"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
18
src/assets/img/tints/Windshield-BrownShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8974)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8974" x1="51.9623" y1="34.0483" x2="51.9623" y2="5.975" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#D0CDC2"/>
|
||||||
|
<stop offset="0.2738" stop-color="#CECBC0"/>
|
||||||
|
<stop offset="0.4097" stop-color="#C9C6B8"/>
|
||||||
|
<stop offset="0.5154" stop-color="#C0BCAB"/>
|
||||||
|
<stop offset="0.6055" stop-color="#B3AD98"/>
|
||||||
|
<stop offset="0.6856" stop-color="#A39B80"/>
|
||||||
|
<stop offset="0.7586" stop-color="#8E8462"/>
|
||||||
|
<stop offset="0.8262" stop-color="#766A3E"/>
|
||||||
|
<stop offset="0.8879" stop-color="#5B4B16"/>
|
||||||
|
<stop offset="0.8993" stop-color="#55450E"/>
|
||||||
|
<stop offset="1" stop-color="#55450E"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
17
src/assets/img/tints/Windshield-GrayShade-BlueTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8970)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8970" x1="51.9669" y1="34.0522" x2="51.9669" y2="5.97896" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CADCDD"/>
|
||||||
|
<stop offset="0.2908" stop-color="#C8DADB"/>
|
||||||
|
<stop offset="0.4353" stop-color="#C1D2D3"/>
|
||||||
|
<stop offset="0.5475" stop-color="#B6C5C6"/>
|
||||||
|
<stop offset="0.6432" stop-color="#A5B2B3"/>
|
||||||
|
<stop offset="0.7282" stop-color="#909A9B"/>
|
||||||
|
<stop offset="0.8057" stop-color="#767C7D"/>
|
||||||
|
<stop offset="0.8761" stop-color="#58595A"/>
|
||||||
|
<stop offset="0.8993" stop-color="#4C4C4D"/>
|
||||||
|
<stop offset="1" stop-color="#4C4C4D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
17
src/assets/img/tints/Windshield-GrayShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_9016)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_9016" x1="51.9669" y1="34.0483" x2="51.9669" y2="5.975" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#D0CDC2"/>
|
||||||
|
<stop offset="0.2978" stop-color="#CECBC0"/>
|
||||||
|
<stop offset="0.4457" stop-color="#C6C3B9"/>
|
||||||
|
<stop offset="0.5606" stop-color="#B9B6AE"/>
|
||||||
|
<stop offset="0.6585" stop-color="#A6A49D"/>
|
||||||
|
<stop offset="0.7456" stop-color="#8E8C87"/>
|
||||||
|
<stop offset="0.8237" stop-color="#71706D"/>
|
||||||
|
<stop offset="0.8959" stop-color="#4E4E4F"/>
|
||||||
|
<stop offset="0.8993" stop-color="#4C4C4D"/>
|
||||||
|
<stop offset="1" stop-color="#4C4C4D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
17
src/assets/img/tints/Windshield-GrayShade-GrayTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8968)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8968" x1="51.9669" y1="34.0483" x2="51.9669" y2="5.975" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#E7E7E8"/>
|
||||||
|
<stop offset="0.2851" stop-color="#E5E5E6"/>
|
||||||
|
<stop offset="0.4267" stop-color="#DDDDDE"/>
|
||||||
|
<stop offset="0.5368" stop-color="#D0D0D1"/>
|
||||||
|
<stop offset="0.6305" stop-color="#BDBDBE"/>
|
||||||
|
<stop offset="0.7139" stop-color="#A5A5A6"/>
|
||||||
|
<stop offset="0.7899" stop-color="#878788"/>
|
||||||
|
<stop offset="0.8589" stop-color="#646465"/>
|
||||||
|
<stop offset="0.8993" stop-color="#4C4C4D"/>
|
||||||
|
<stop offset="1" stop-color="#4C4C4D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
17
src/assets/img/tints/Windshield-GrayShade-GreenTint.svg
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8930)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8930" x1="51.9669" y1="34.0648" x2="51.9669" y2="5.99157" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CBE9DD"/>
|
||||||
|
<stop offset="0.2841" stop-color="#C9E7DB"/>
|
||||||
|
<stop offset="0.4252" stop-color="#C3DFD4"/>
|
||||||
|
<stop offset="0.5349" stop-color="#B8D2C8"/>
|
||||||
|
<stop offset="0.6283" stop-color="#A9BFB7"/>
|
||||||
|
<stop offset="0.7114" stop-color="#96A7A0"/>
|
||||||
|
<stop offset="0.7871" stop-color="#7D8985"/>
|
||||||
|
<stop offset="0.8559" stop-color="#616665"/>
|
||||||
|
<stop offset="0.8993" stop-color="#4C4C4D"/>
|
||||||
|
<stop offset="1" stop-color="#4C4C4D"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.2 KiB |
18
src/assets/img/tints/Windshield-GreenShade-BlueTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8918)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8918" x1="51.976" y1="34.0522" x2="51.976" y2="5.97896" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CADCDD"/>
|
||||||
|
<stop offset="0.2653" stop-color="#C8DBDB"/>
|
||||||
|
<stop offset="0.3972" stop-color="#C0D6D5"/>
|
||||||
|
<stop offset="0.4996" stop-color="#B3CFCB"/>
|
||||||
|
<stop offset="0.5869" stop-color="#A0C4BD"/>
|
||||||
|
<stop offset="0.6645" stop-color="#88B6AA"/>
|
||||||
|
<stop offset="0.7353" stop-color="#6AA593"/>
|
||||||
|
<stop offset="0.8009" stop-color="#469177"/>
|
||||||
|
<stop offset="0.8607" stop-color="#1E7A58"/>
|
||||||
|
<stop offset="0.8993" stop-color="#006941"/>
|
||||||
|
<stop offset="1" stop-color="#006941"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
18
src/assets/img/tints/Windshield-GreenShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8972)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8972" x1="52.0031" y1="34.0483" x2="52.0031" y2="5.975" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#D0CDC2"/>
|
||||||
|
<stop offset="0.2632" stop-color="#CECCC1"/>
|
||||||
|
<stop offset="0.394" stop-color="#C6C8BC"/>
|
||||||
|
<stop offset="0.4956" stop-color="#B9C2B4"/>
|
||||||
|
<stop offset="0.5823" stop-color="#A6B9A8"/>
|
||||||
|
<stop offset="0.6593" stop-color="#8EAD99"/>
|
||||||
|
<stop offset="0.7295" stop-color="#709F86"/>
|
||||||
|
<stop offset="0.7947" stop-color="#4C8E70"/>
|
||||||
|
<stop offset="0.854" stop-color="#247A57"/>
|
||||||
|
<stop offset="0.8993" stop-color="#006941"/>
|
||||||
|
<stop offset="1" stop-color="#006941"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
18
src/assets/img/tints/Windshield-GreenShade-GreenTint.svg
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="url(#paint0_linear_841_8894)" stroke="black"/>
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="paint0_linear_841_8894" x1="51.976" y1="34.0648" x2="51.976" y2="5.99157" gradientUnits="userSpaceOnUse">
|
||||||
|
<stop stop-color="#CBE9DD"/>
|
||||||
|
<stop offset="0.265" stop-color="#C9E8DB"/>
|
||||||
|
<stop offset="0.3966" stop-color="#C1E3D5"/>
|
||||||
|
<stop offset="0.4989" stop-color="#B4DACB"/>
|
||||||
|
<stop offset="0.5861" stop-color="#A1CFBD"/>
|
||||||
|
<stop offset="0.6636" stop-color="#89BFAA"/>
|
||||||
|
<stop offset="0.7343" stop-color="#6BAC93"/>
|
||||||
|
<stop offset="0.7998" stop-color="#479678"/>
|
||||||
|
<stop offset="0.8595" stop-color="#1F7D59"/>
|
||||||
|
<stop offset="0.8993" stop-color="#006941"/>
|
||||||
|
<stop offset="1" stop-color="#006941"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.3 KiB |
3
src/assets/img/tints/Windshield-NoShade-BlueTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="#CBDDDE" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 662 B |
3
src/assets/img/tints/Windshield-NoShade-BrownTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="#D1CEC3" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 662 B |
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="#5D564C" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 662 B |
3
src/assets/img/tints/Windshield-NoShade-DarkGrayTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="#D3D3D3" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 662 B |
3
src/assets/img/tints/Windshield-NoShade-GrayTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="#E9E9EB" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 662 B |
3
src/assets/img/tints/Windshield-NoShade-GreenTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="#CBE9DD" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 662 B |
3
src/assets/img/tints/Windshield-NoShade-NoTint.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="white" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 660 B |
3
src/assets/img/tints/Windshield-NoShade-Privacy.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
<svg width="104" height="40" viewBox="0 0 104 40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M51.9768 32.4623C54.8365 32.4623 73.392 32.1997 87.6574 34.0091C90.1732 34.3302 91.889 32.1711 91.9744 30.7698C92.5182 22.8924 84.227 12.0979 84.227 12.0979C84.227 12.0979 81.7113 8.18778 75.6493 7.42988C75.6493 7.42988 61.3546 6 52.0061 6C43.2576 6 28.3617 7.42988 28.3617 7.42988C22.3009 8.18778 19.7851 12.0967 19.7851 12.0967C19.7851 12.0967 11.3793 22.9222 12.0366 30.7698C12.1232 31.9371 13.8378 34.3302 16.3536 34.0091C30.5641 32.1997 49.1184 32.4623 51.9768 32.4623Z" fill="#626167" stroke="black"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 662 B |
|
|
@ -1,7 +1,7 @@
|
||||||
<!-- Documented in confluence https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Component -->
|
<!-- Documented in confluence https://safelite.atlassian.net/wiki/spaces/DC/pages/76644418/Button+Question+Component -->
|
||||||
<template>
|
<template>
|
||||||
<div :class="isOverflowScrollable ? 'button-question button-question-overflow' : 'button-question'">
|
<div :class="isOverflowScrollable ? 'button-question button-question-overflow' : 'button-question'">
|
||||||
<div v-if="questionText" class="mt-5 mb-4 d-flex">
|
<div v-if="questionText" :class="[this.buttonType === 'radio' ? ['mt-2', 'mb-0'] : ['mt-5', 'mb-4'], 'd-flex']">
|
||||||
<span class="fs-5 fw-bold w-100" :class="this.buttonType === 'radio' ? 'text-start' : 'text-center'">{{ questionText }}</span>
|
<span class="fs-5 fw-bold w-100" :class="this.buttonType === 'radio' ? 'text-start' : 'text-center'">{{ questionText }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="w-100 d-flex justify-content-center">
|
<div class="w-100 d-flex justify-content-center">
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
:key="answer.Name ? answer.Name : answer"
|
:key="answer.Name ? answer.Name : answer"
|
||||||
@isCheckedChanged="handleCheckedChanged"
|
@isCheckedChanged="handleCheckedChanged"
|
||||||
:buttonID="answer.Name ? groupName + '-' + answer.Name : groupName + '-' + answer"
|
:buttonID="answer.Name ? groupName + '-' + answer.Name : groupName + '-' + answer"
|
||||||
:value="answer.Name ? answer.Name : 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"
|
||||||
|
|
@ -23,8 +23,8 @@
|
||||||
:selectingInitiatesLoad="selectingInitiatesLoad"
|
:selectingInitiatesLoad="selectingInitiatesLoad"
|
||||||
:loaderColor="loaderColor"
|
:loaderColor="loaderColor"
|
||||||
:loaderPosition="loaderPosition"
|
:loaderPosition="loaderPosition"
|
||||||
:isWide="isWide"
|
:isWide=isWide
|
||||||
:isRequired="isRequired"
|
:isRequired=isRequired
|
||||||
:buttonImage="answer.AnswerImageUrl"
|
:buttonImage="answer.AnswerImageUrl"
|
||||||
:buttonImageId="answer.ImageId"
|
:buttonImageId="answer.ImageId"
|
||||||
:altText="answer.Name ? answer.Name : answer"
|
:altText="answer.Name ? answer.Name : answer"
|
||||||
|
|
@ -80,6 +80,7 @@ export default {
|
||||||
modelValue: Array,
|
modelValue: Array,
|
||||||
validationRules: String,
|
validationRules: String,
|
||||||
suppressError: Boolean,
|
suppressError: Boolean,
|
||||||
|
useTextForValue: Boolean,
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
getFieldSetClasses() {
|
getFieldSetClasses() {
|
||||||
|
|
@ -122,6 +123,12 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
getValues(answer){
|
||||||
|
if (this.useTextForValue){
|
||||||
|
return answer.Text
|
||||||
|
}
|
||||||
|
return answer.Name ? answer.Name : answer;
|
||||||
|
},
|
||||||
handleCheckedChanged(val) {
|
handleCheckedChanged(val) {
|
||||||
if(this.isMultiSelect && this.selectedValues) {
|
if(this.isMultiSelect && this.selectedValues) {
|
||||||
// Add or remove item to array of data to emit
|
// Add or remove item to array of data to emit
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import vinInformation from "@/common-components/vin-information/vin-information";
|
||||||
|
|
||||||
|
describe("vinInformation.vue", () => {
|
||||||
|
it("Should return input class active if isActive is true", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(vinInformation);
|
||||||
|
|
||||||
|
await wrapper.setData({
|
||||||
|
isActive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
wrapper.vm.toggleClass()
|
||||||
|
|
||||||
|
expect(wrapper.vm.isActive).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
78
src/common-components/vin-information/vin-information.vue
Normal file
|
|
@ -0,0 +1,78 @@
|
||||||
|
<template>
|
||||||
|
<div class="vin-information">
|
||||||
|
<div class="vin-toggle d-inline-flex" :class="[isActive ? 'active' : '']" @click="toggleClass()">
|
||||||
|
<textLink :text="HeadlineText" linkType="text" href="#!" />
|
||||||
|
</div>
|
||||||
|
<div class="vin-info">
|
||||||
|
<div class="mt-3" v-html="BodyText"></div>
|
||||||
|
<img :src="OptionalImage" alt="" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
import textLink from "@/ux-components/text-link/text-link";
|
||||||
|
export default {
|
||||||
|
name: "vinInformation",
|
||||||
|
components: {
|
||||||
|
textLink,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
isActive: false,
|
||||||
|
HeadlineText: "Where can I find my VIN?",
|
||||||
|
BodyText: "<p class='mb-2'>You can find your VIN in a few places:</p> <ol> <li>Driver side windshield</li> <li>Driver side doorjamb</li> <li>Vehicle registration card</li> <li>Auto insurance card or app</li> </ol>",
|
||||||
|
OptionalImage: "https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/vin_location.svg?sfvrsn=63a9a2cf_3",
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleClass: function(event){
|
||||||
|
this.isActive = !this.isActive;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.vin-information {
|
||||||
|
p,li {
|
||||||
|
font-size: .875rem;
|
||||||
|
color: $gray-600;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
font-size: .875rem;
|
||||||
|
}
|
||||||
|
.vin-toggle {
|
||||||
|
&:after {
|
||||||
|
content: "";
|
||||||
|
transition: all .5s ease;
|
||||||
|
background-image: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 8.9' xml:space='preserve'%3e%3cpath d='M8 8.9c-.2 0-.5-.1-.6-.3L.3 1.5C.1 1.4 0 1.1 0 .9 0 .7.1.4.3.3.4.1.7 0 .9 0c.2 0 .5.1.6.3L8 6.7 14.5.2c.1-.1.4-.2.6-.2.2 0 .5.1.6.3s.3.4.3.6c0 .2-.1.5-.3.6L8.6 8.6c-.1.2-.4.3-.6.3z' fill='%231474a2'/%3e%3c/svg%3e");
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right center;
|
||||||
|
margin-left: .5rem;
|
||||||
|
width: 16px;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
&.active:after {
|
||||||
|
transform: rotate(180deg);
|
||||||
|
}
|
||||||
|
&.active + .vin-info {
|
||||||
|
max-height: 500px;
|
||||||
|
transition: all 250ms ease-in;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.vin-info {
|
||||||
|
max-height: 0;
|
||||||
|
transition: all 250ms ease-out;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
img {
|
||||||
|
width: 117%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
9
src/constants/damage-locations-cms.js
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
const damageLocationsCms = {
|
||||||
|
WINDSHIELD: "WINDSHIELD",
|
||||||
|
SIDEDOOR: "SIDEDOOR",
|
||||||
|
REARWINDOW: "REARWINDOW",
|
||||||
|
DRIVERSIDE: "DRIVERSIDE",
|
||||||
|
PASSENGERSIDE: "PASSENGERSIDE",
|
||||||
|
};
|
||||||
|
|
||||||
|
export { damageLocationsCms };
|
||||||
8
src/constants/damage-locations-parts.js
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
const damageLocationsParts = {
|
||||||
|
WINDSHIELD: "Windshield",
|
||||||
|
DRIVER: "Driver",
|
||||||
|
PASSENGER: "Passenger",
|
||||||
|
REAR: "Rear",
|
||||||
|
};
|
||||||
|
|
||||||
|
export { damageLocationsParts };
|
||||||
57
src/constants/dynamictext-mapper.js
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
// Used to support custom (non-state) related dynamic text.
|
||||||
|
// Example: {custom:glassName}, each key in the array is the value after custom:, like 'glassname'
|
||||||
|
// Please use lowercase only so that we don't have to worry about case sensitivity.
|
||||||
|
|
||||||
|
const customMappings = {
|
||||||
|
formattedglassname: [
|
||||||
|
{ key: 'Windshield Single', transformedValue: 'windshield' },
|
||||||
|
{ key: 'Windshield Driver', transformedValue: 'driver side split windshield' },
|
||||||
|
{ key: 'Windshield Passenger', transformedValue: 'passenger side split windshield' },
|
||||||
|
{ key: 'Rear Stationary', transformedValue: 'rear window' },
|
||||||
|
{ key: 'Rear Slider', transformedValue: 'rear window' },
|
||||||
|
{ key: 'Driver Front', transformedValue: 'driver side front door' },
|
||||||
|
{ key: 'Driver Back', transformedValue: 'driver side back door' },
|
||||||
|
{ key: 'Driver Vent', transformedValue: 'driver side vent glass' },
|
||||||
|
{ key: 'Driver Quarter', transformedValue: 'driver side quarter panel' },
|
||||||
|
{ key: 'Driver SideDoor', transformedValue: 'driver side sliding door' },
|
||||||
|
{ key: 'Passenger Front', transformedValue: 'passenger side front door' },
|
||||||
|
{ key: 'Passenger Back', transformedValue: 'passenger side back door' },
|
||||||
|
{ key: 'Passenger Vent', transformedValue: 'passenger side vent glass' },
|
||||||
|
{ key: 'Passenger Quarter', transformedValue: 'passenger side quarter panel' },
|
||||||
|
{ key: 'Passenger SlideDoor', transformedValue: 'passenger side sliding door' },
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets an instance of a string where the dynamic portion of the text {custom:KeyName}
|
||||||
|
// is replaced by a value from the above map.
|
||||||
|
// If the value isn't found, return the original dynamic string without replacement
|
||||||
|
export function getCustomTransformValue(dynamicString, key) {
|
||||||
|
|
||||||
|
// Get array key from the dynamic string
|
||||||
|
const regexExp = new RegExp("{(.*?):(.*?)}", "g");
|
||||||
|
const matches = [...dynamicString.matchAll(regexExp)];
|
||||||
|
|
||||||
|
if (matches.length === 0) {
|
||||||
|
return dynamicString;
|
||||||
|
}
|
||||||
|
|
||||||
|
const arrayKey = matches[0][2];
|
||||||
|
|
||||||
|
// Get the array of possible values based on the key name.
|
||||||
|
const transformArray = customMappings[arrayKey.toLowerCase()];
|
||||||
|
|
||||||
|
if(transformArray === undefined) {
|
||||||
|
return dynamicString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the value where the name matches the key name, there should only be one so find() is used.
|
||||||
|
const mapObject = transformArray.find(map => map.key.toLowerCase() === key.toLowerCase());
|
||||||
|
|
||||||
|
if(mapObject === undefined){
|
||||||
|
return dynamicString;
|
||||||
|
}
|
||||||
|
|
||||||
|
const finalString = dynamicString.replace(`{custom:${arrayKey}}`, mapObject.transformedValue);
|
||||||
|
|
||||||
|
return finalString
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,10 @@ const endpoints = {
|
||||||
url: "/vehicle/api/v1/vehicle/Lookup",
|
url: "/vehicle/api/v1/vehicle/Lookup",
|
||||||
method: "POST",
|
method: "POST",
|
||||||
},
|
},
|
||||||
|
GetPartsOrQuestions: {
|
||||||
|
url: "/parts/api/v1/parts/parts-or-questions",
|
||||||
|
method: "POST",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export { endpoints };
|
export { endpoints };
|
||||||
|
|
|
||||||
|
|
@ -11,12 +11,13 @@ const storeActions = {
|
||||||
GET_EVOX_IMAGE: "getEvoxImage",
|
GET_EVOX_IMAGE: "getEvoxImage",
|
||||||
LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms",
|
LOOKUP_VEHICLE_BY_YMMS: "lookupVehicleByYmms",
|
||||||
LOOKUP_VEHICLE_BY_VIN: "lookupVehicleByVin",
|
LOOKUP_VEHICLE_BY_VIN: "lookupVehicleByVin",
|
||||||
|
GET_PARTS_OR_QUESTIONS: "getPartsOrQuestions",
|
||||||
|
|
||||||
// DEPENDENCY MUTATIONS
|
// DEPENDENCY MUTATIONS
|
||||||
RESET_VEHICLE_AND_DEPS: "resetVehicleAndDependencies",
|
RESET_VEHICLE_STATE_AND_DEPENDENCIES: "resetVehicleAndDependencies",
|
||||||
RESET_DAMAGE_AND_DEPS: "resetDamageAndDependencies",
|
RESET_DAMAGE_STATE_AND_DEPENDENCIES: "resetDamageAndDependencies",
|
||||||
RESET_REGISTRATION_AND_DEPS: "resetRegistrationAndDependencies",
|
RESET_REGISTRATION_STATE_AND_DEPENDENCIES: "resetRegistrationAndDependencies",
|
||||||
RESET_PARTS_AND_DEPS: "resetPartsAndDependencies",
|
RESET_PARTS_STATE_AND_DEPENDENCIES: "resetPartsAndDependencies",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { storeActions };
|
export { storeActions };
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,23 @@ const storeMutations = {
|
||||||
UPDATE_VEHICLE_IMAGE_URL: "updateVehicleImageUrl",
|
UPDATE_VEHICLE_IMAGE_URL: "updateVehicleImageUrl",
|
||||||
UPDATE_VEHICLE_IMAGE_VIF_NUMBER: "updateVehicleImageVifNumber",
|
UPDATE_VEHICLE_IMAGE_VIF_NUMBER: "updateVehicleImageVifNumber",
|
||||||
UPDATE_VEHICLE_IMAGE_COLOR: "updateVehicleImageColor",
|
UPDATE_VEHICLE_IMAGE_COLOR: "updateVehicleImageColor",
|
||||||
|
UPDATE_IS_REPAIR: "updateIsRepair",
|
||||||
|
UPDATE_NUMBER_OF_CHIPS: "updateNumberOfChips",
|
||||||
|
UPDATE_GLASS_TO_REPLACE: "updateGlassToReplace",
|
||||||
|
UPDATE_PARTS: "updateParts",
|
||||||
|
|
||||||
// EVENT BUS MUTATIONS
|
// EVENT BUS MUTATIONS
|
||||||
ADD_EVENT_TO_BUS: "addEventToBus",
|
ADD_EVENT_TO_BUS: "addEventToBus",
|
||||||
REMOVE_EVENT_FROM_BUS: "removeEventFromBus",
|
REMOVE_EVENT_FROM_BUS: "removeEventFromBus",
|
||||||
|
|
||||||
// DEPENDENCY MUTATIONS
|
// DEPENDENCY MUTATIONS
|
||||||
RESET_VEHICLE_AND_DEPS: "resetVehicleAndDependencies",
|
RESET_VEHICLE_STATE: "resetVehicleState",
|
||||||
RESET_DAMAGE_AND_DEPS: "resetDamageAndDependencies",
|
RESET_DAMAGE_STATE: "resetDamageState",
|
||||||
RESET_REGISTRATION_AND_DEPS: "resetRegistrationAndDependencies",
|
RESET_REGISTRATION_STATE: "resetRegistrationState",
|
||||||
RESET_PARTS_AND_DEPS: "resetPartsAndDependencies",
|
RESET_PARTS_STATE: "resetPartsState",
|
||||||
|
|
||||||
|
// OTHER MUTATIONS
|
||||||
|
UPDATE_PAGE_DATA: "updatePageData",
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
95
src/constants/tint-mapper.js
Normal file
|
|
@ -0,0 +1,95 @@
|
||||||
|
|
||||||
|
// TintMap with array keys by location, lowercase to avoid as much string mismatching as possible.
|
||||||
|
// Src assumes you have a @/assets/img/tints/, making the final value @/assets/img/tints/{Src} in the markup.
|
||||||
|
// See vehicle-parts for implementation example.
|
||||||
|
const tintMap = {
|
||||||
|
other: [
|
||||||
|
// Blue Shade
|
||||||
|
{ name: "blue tint, blue shade", src: "Glass-BlueShade-BlueTint.svg" },
|
||||||
|
{ name: "brown tint, blue shade", src: "Glass-BlueShade-BrownTint.svg" },
|
||||||
|
{ name: "gray tint, blue shade", src: "Glass-BlueShade-GrayTint.svg" },
|
||||||
|
{ name: "green tint, blue shade", src: "Glass-BlueShade-GreenTint.svg" },
|
||||||
|
{ name: "blue shade", src: "Glass-BlueShade-NoTint.svg" },
|
||||||
|
|
||||||
|
// Brown Shade
|
||||||
|
{ name: "brown tint, brown shade", src: "Glass-BrownShade-BrownTint.svg" },
|
||||||
|
|
||||||
|
// Gray Shade
|
||||||
|
{ name: "blue tint, gray shade", src: "Glass-GrayShade-BlueTint.svg" },
|
||||||
|
{ name: "brown tint, gray shade", src: "Glass-GrayShade-BrownTint.svg" },
|
||||||
|
{ name: "gray tint, gray shade", src: "Glass-GrayShade-GrayTint.svg" },
|
||||||
|
{ name: "green tint, gray shade", src: "Glass-GrayShade-GreenTint.svg" },
|
||||||
|
|
||||||
|
// Green Shade
|
||||||
|
{ name: "blue tint, green shade", src: "Glass-GreenShade-BlueTint.svg" },
|
||||||
|
{ name: "brown tint, green shade", src: "Glass-GreenShade-BrownTint.svg" },
|
||||||
|
{ name: "green tint, green shade", src: "Glass-GreenShade-GreenTint.svg" },
|
||||||
|
|
||||||
|
// Tints Only
|
||||||
|
{ name: "blue tint", src: "Glass-NoShade-BlueTint.svg" },
|
||||||
|
{ name: "brown tint", src: "Glass-NoShade-BrownTint.svg" },
|
||||||
|
{ name: "dark brown tint", src: "Glass-NoShade-DarkBrownTint.svg" },
|
||||||
|
{ name: "dark gray tint", src: "Glass-NoShade-DarkGrayTint.svg" },
|
||||||
|
{ name: "gray tint", src: "Glass-NoShade-GrayTint.svg" },
|
||||||
|
{ name: "green tint", src: "Glass-NoShade-GreenTint.svg" },
|
||||||
|
{ name: "gray tint privacy", src: "Glass-NoShade-Privacy.svg" },
|
||||||
|
|
||||||
|
// No shade or tint
|
||||||
|
{ name: "no shade, no tint", src: "Glass-NoShade-NoTint.svg" }, // ???
|
||||||
|
],
|
||||||
|
|
||||||
|
windshield: [
|
||||||
|
// Blue Shade
|
||||||
|
{ name: "blue tint, blue shade", src: "Windshield-BlueShade-BlueTint.svg" },
|
||||||
|
{ name: "brown tint, blue shade", src: "Windshield-BlueShade-BrownTint.svg" },
|
||||||
|
{ name: "gray tint, blue shade", src: "Windshield-BlueShade-GrayTint.svg" },
|
||||||
|
{ name: "green tint, blue shade", src: "Windshield-BlueShade-GreenTint.svg" },
|
||||||
|
{ name: "blue shade", src: "Windshield-BlueShade-NoTint.svg" },
|
||||||
|
|
||||||
|
// Brown Shade
|
||||||
|
{ name: "brown tint, brown shade", src: "Windshield-BrownShade-BrownTint.svg" },
|
||||||
|
|
||||||
|
// Gray Shade
|
||||||
|
{ name: "blue tint, gray shade", src: "Windshield-GrayShade-BlueTint.svg" },
|
||||||
|
{ name: "brown tint, gray shade", src: "Windshield-GrayShade-BrownTint.svg" },
|
||||||
|
{ name: "gray tint, gray shade", src: "Windshield-GrayShade-GrayTint.svg" },
|
||||||
|
{ name: "green tint, gray shade", src: "Windshield-GrayShade-GreenTint.svg" },
|
||||||
|
|
||||||
|
// Green Shade
|
||||||
|
{ name: "blue tint, green shade", src: "Windshield-GreenShade-BlueTint.svg" },
|
||||||
|
{ name: "brown tint, green shade", src: "Windshield-GreenShade-BrownTint.svg" },
|
||||||
|
{ name: "green tint, green shade", src: "Windshield-GreenShade-GreenTint.svg" },
|
||||||
|
|
||||||
|
// Tints Only
|
||||||
|
{ name: "blue tint", src: "Windshield-NoShade-BlueTint.svg" },
|
||||||
|
{ name: "brown tint", src: "Windshield-NoShade-BrownTint.svg" },
|
||||||
|
{ name: "dark brown tint", src: "Windshield-NoShade-DarkBrownTint.svg" },
|
||||||
|
{ name: "dark gray tint", src: "Windshield-NoShade-DarkGrayTint.svg" },
|
||||||
|
{ name: "gray tint", src: "Windshield-NoShade-GrayTint.svg" },
|
||||||
|
{ name: "green tint", src: "Windshield-NoShade-GreenTint.svg" },
|
||||||
|
{ name: "gray tint privacy", src: "Windshield-NoShade-Privacy.svg" },
|
||||||
|
|
||||||
|
// No shade or tint
|
||||||
|
{ name: "no shade, no tint", src: "Windshield-NoShade-NoTint.svg" }, // ???
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the tint image source string given the glass location, and the tint description (like 'Green Tint')
|
||||||
|
// Use lowered strings here to try to avoid mismatch. Returns an empty string if array key doesn't exist.
|
||||||
|
// Returns undefined if no items are found.
|
||||||
|
export function getTintImage(glassLocation, colorString) {
|
||||||
|
|
||||||
|
// Windshield glass has special images, all other glass uses the same though.
|
||||||
|
if(glassLocation.toLowerCase() !== 'windshield'){
|
||||||
|
glassLocation = 'other';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tintMap[glassLocation.toLowerCase()] === undefined) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
const tintImageSource = tintMap[glassLocation.toLowerCase()].find(item => item.name.toLowerCase() == colorString.toLowerCase())
|
||||||
|
|
||||||
|
return tintImageSource;
|
||||||
|
}
|
||||||
|
|
@ -19,7 +19,11 @@ export default {
|
||||||
}).then(
|
}).then(
|
||||||
(response) => {
|
(response) => {
|
||||||
if (response.status == httpStatusCodes.OK) {
|
if (response.status == httpStatusCodes.OK) {
|
||||||
resolve(response);
|
if(response.data == undefined) {
|
||||||
|
reject(response);
|
||||||
|
}else{
|
||||||
|
resolve(response);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
reject(response);
|
reject(response);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,28 @@ import { storeActions } from "@/constants/store-actions";
|
||||||
import { storeMutations } from "@/constants/store-mutations.js";
|
import { storeMutations } from "@/constants/store-mutations.js";
|
||||||
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js";
|
import { navigationScenarios } from "@/router/router-constants/navigation-scenarios.js";
|
||||||
import { vehicleCategories } from "@/constants/vehicle-categories.js";
|
import { vehicleCategories } from "@/constants/vehicle-categories.js";
|
||||||
|
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||||
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
|
|
||||||
export function getMountOptions(mockData) {
|
export function getMountOptions(mockData) {
|
||||||
// Define our mocks to attached to the 'global' object for Vue/Jest.
|
// Define our mocks to attached to the 'global' object for Vue/Jest.
|
||||||
const mocks = {};
|
const mocks = {};
|
||||||
|
|
||||||
|
//this is mocking if you use the mixin directly(baseMixin.methods.dispatchNonBlockingStoreAction) vs this.dispatchNonBlockingStoreAction
|
||||||
|
if (mockData.actionList !== undefined) {
|
||||||
|
baseMixin.methods.dispatchNonBlockingStoreAction = jest.fn();
|
||||||
|
baseMixin.methods.dispatchNonBlockingStoreAction.mockImplementation((actionName) => {
|
||||||
|
let actionFilterResult = mockData.actionList.filter(
|
||||||
|
(x) => x.actionName == actionName
|
||||||
|
);
|
||||||
|
|
||||||
|
if (actionFilterResult.length > 0 && actionFilterResult.length === 1) {
|
||||||
|
return Promise.resolve({
|
||||||
|
data: actionFilterResult[0].data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
mocks.dispatchNonBlockingStoreAction = jest.fn();
|
mocks.dispatchNonBlockingStoreAction = jest.fn();
|
||||||
mocks.dispatchNonBlockingStoreAction.mockImplementation((actionName) => {
|
mocks.dispatchNonBlockingStoreAction.mockImplementation((actionName) => {
|
||||||
let actionFilterResult = mockData.actionList.filter(
|
let actionFilterResult = mockData.actionList.filter(
|
||||||
|
|
@ -25,10 +42,13 @@ export function getMountOptions(mockData) {
|
||||||
mocks.storeMutations = storeMutations;
|
mocks.storeMutations = storeMutations;
|
||||||
mocks.navigationScenarios = navigationScenarios;
|
mocks.navigationScenarios = navigationScenarios;
|
||||||
mocks.vehicleCategories = vehicleCategories;
|
mocks.vehicleCategories = vehicleCategories;
|
||||||
|
mocks.fmgPageValues = fmgPageValues;
|
||||||
|
|
||||||
// Mock $store and $router when accessing this.$store/$router
|
// Mock $store and $router when accessing this.$store/$router
|
||||||
mocks.$store = mockData.store;
|
mocks.$store = mockData.store;
|
||||||
mocks.$router = mockData.router;
|
mocks.$router = mockData.router;
|
||||||
|
mocks.$route = mockData.route;
|
||||||
|
|
||||||
|
|
||||||
const global = {
|
const global = {
|
||||||
mocks: mocks,
|
mocks: mocks,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,15 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="container-fluid container-shadow p-2 rounded-3">
|
<div class="container-fluid container-shadow p-2 rounded-3">
|
||||||
|
<div class="row my-4">
|
||||||
|
<div class="col">
|
||||||
|
<h4 class="m-0 p-2 bg-light rounded">VIN Information</h4>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row my-2">
|
||||||
|
<div class="col">
|
||||||
|
<vinInformation/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row my-4">
|
<div class="row my-4">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<h4 class="m-0 p-2 bg-light rounded">Text Input</h4>
|
<h4 class="m-0 p-2 bg-light rounded">Text Input</h4>
|
||||||
|
|
@ -1134,6 +1144,7 @@
|
||||||
import textLink from "@/ux-components/text-link/text-link";
|
import textLink from "@/ux-components/text-link/text-link";
|
||||||
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
import textboxQuestion from "@/common-components/textbox-question/textbox-question";
|
||||||
import dropdownQuestion from "@/common-components/dropdown-question/dropdown-question";
|
import dropdownQuestion from "@/common-components/dropdown-question/dropdown-question";
|
||||||
|
import vinInformation from "@/common-components/vin-information/vin-information";
|
||||||
export default {
|
export default {
|
||||||
name: "App",
|
name: "App",
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -1148,6 +1159,7 @@
|
||||||
textLink,
|
textLink,
|
||||||
textboxQuestion,
|
textboxQuestion,
|
||||||
dropdownQuestion,
|
dropdownQuestion,
|
||||||
|
vinInformation,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ export default {
|
||||||
},
|
},
|
||||||
resetDependentState() {
|
resetDependentState() {
|
||||||
// Invokes
|
// Invokes
|
||||||
store.dispatch(storeActions.RESET_PARTS_AND_DEPS);
|
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||||
},
|
},
|
||||||
onSubmit(values) {
|
onSubmit(values) {
|
||||||
window.alert('Success! Submitted values: ' + JSON.stringify(values, null ,2))
|
window.alert('Success! Submitted values: ' + JSON.stringify(values, null ,2))
|
||||||
|
|
|
||||||
|
|
@ -1,20 +1,18 @@
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<div class="container-fluid nested-radio">
|
<div class="container-fluid nested-radio">
|
||||||
<div class="row mb-1">
|
<div class="row mb-1">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<listCard
|
<listCard
|
||||||
groupName="listcard1"
|
groupName="listcard1"
|
||||||
isWide="true"
|
isWide="true"
|
||||||
buttonImage="https://digitalconsumercms-dev.safelite.com/images/default-source/damage-options/car.svg?sfvrsn=1468d7f1_3"
|
buttonImage="https://digitalconsumercms-dev.safelite.com/images/default-source/damage-options/car.svg?sfvrsn=1468d7f1_3"
|
||||||
buttonLabel="Green Tint, Blue Shade"
|
buttonLabel="Green Tint, Blue Shade"
|
||||||
buttonID="radio1"
|
buttonID="radio1"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-1">
|
<div class="row mb-1">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<p class="mb-0 fw-bold">Ok, select the features</p>
|
|
||||||
<buttonQuestion
|
<buttonQuestion
|
||||||
buttonType="radio"
|
buttonType="radio"
|
||||||
groupName="Demo Group"
|
groupName="Demo Group"
|
||||||
|
|
@ -23,22 +21,22 @@
|
||||||
value="test button"
|
value="test button"
|
||||||
screenReaderOnlyText="rain sensor, solar, 3rd visor band"
|
screenReaderOnlyText="rain sensor, solar, 3rd visor band"
|
||||||
:answers="demoArray"
|
:answers="demoArray"
|
||||||
|
questionText="ok now select your features"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<listCard
|
<listCard
|
||||||
groupName="listcard1"
|
groupName="listcard1"
|
||||||
isWide="true"
|
isWide="true"
|
||||||
buttonImage="https://digitalconsumercms-dev.safelite.com/images/default-source/damage-options/car.svg?sfvrsn=1468d7f1_3"
|
buttonImage="https://digitalconsumercms-dev.safelite.com/images/default-source/damage-options/car.svg?sfvrsn=1468d7f1_3"
|
||||||
buttonLabel="Green Tint"
|
buttonLabel="Green Tint"
|
||||||
buttonID="radio2"
|
buttonID="radio2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -56,9 +54,9 @@ export default {
|
||||||
demoArray: [
|
demoArray: [
|
||||||
"rain sensor, solar, 3rd visor band",
|
"rain sensor, solar, 3rd visor band",
|
||||||
"rain sensor, heated glass, solar, 3rd visor band",
|
"rain sensor, heated glass, solar, 3rd visor band",
|
||||||
]
|
],
|
||||||
}
|
};
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
@ -66,10 +64,11 @@ export default {
|
||||||
.nested-radio {
|
.nested-radio {
|
||||||
.ui-radio {
|
.ui-radio {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
margin: .25rem 0;
|
margin: 0.25rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
font-size: .875rem;
|
font-size: 0.875rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
96
src/layouts/part-questions/part-questions.vue
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall">
|
||||||
|
<funnelHeader ref="funnelHeader" />
|
||||||
|
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage="false" />
|
||||||
|
<funnelSubHeader ref="funnelSubHeader" />
|
||||||
|
<h1>Part Questions Page Placeholder</h1>
|
||||||
|
<funnelFooter ref="funnelFooter" @back-clicked="backButtonAction" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Components
|
||||||
|
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
||||||
|
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||||
|
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import {
|
||||||
|
fetchCmsContentForPage
|
||||||
|
} from "@/helpers/cms-content-helper";
|
||||||
|
import {
|
||||||
|
settleAllPromises
|
||||||
|
} from "@/helpers/layout-helper";
|
||||||
|
import {
|
||||||
|
storeMutations
|
||||||
|
} from "@/constants/store-mutations";
|
||||||
|
import {
|
||||||
|
storeActions
|
||||||
|
} from "@/constants/store-actions";
|
||||||
|
import store from "@/store";
|
||||||
|
import {
|
||||||
|
fmgPageValues
|
||||||
|
} from "@/router/router-constants/fmgPage-values";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "part-questions",
|
||||||
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
// Call APIs
|
||||||
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
|
||||||
|
// Settle promises and get results
|
||||||
|
const promiseResultMap = [{
|
||||||
|
resultKey: "cmsContent",
|
||||||
|
promise: cmsContentPromise,
|
||||||
|
}, ];
|
||||||
|
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
|
// Call the "next" function to complete the transition to this page.
|
||||||
|
next((vm) => {
|
||||||
|
vm.$refs.funnelHeader.initializeComponent(
|
||||||
|
resultMap.cmsContent.FunnelHeaderWidget
|
||||||
|
);
|
||||||
|
vm.$refs.vehicleBanner.initializeComponent(
|
||||||
|
resultMap.cmsContent.VehicleBannerWidget
|
||||||
|
);
|
||||||
|
vm.$refs.funnelSubHeader.initializeComponent(
|
||||||
|
resultMap.cmsContent.FunnelSubHeaderWidget
|
||||||
|
);
|
||||||
|
vm.$refs.funnelFooter.initializeComponent(
|
||||||
|
resultMap.cmsContent.FunnelFooterWidget
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
backButtonAction() {
|
||||||
|
// route to move backwards
|
||||||
|
this.$router.navigate(
|
||||||
|
this.navigationScenarios.CLICKED_BACK,
|
||||||
|
this.$route
|
||||||
|
);
|
||||||
|
},
|
||||||
|
arePagePrerequisitesValid() {
|
||||||
|
if (Object.keys(store.getters.pageData(fmgPageValues.PART_QUESTIONS)).length !== 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
resetDependentState() {
|
||||||
|
// Set
|
||||||
|
store.commit(storeMutations.UPDATE_PARTS, null);
|
||||||
|
|
||||||
|
// Invokes
|
||||||
|
store.dispatch(storeActions.RESET_PARTS_AND_DEPS);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {},
|
||||||
|
components: {
|
||||||
|
funnelHeader,
|
||||||
|
vehicleBanner,
|
||||||
|
funnelSubHeader,
|
||||||
|
funnelFooter,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
71
src/layouts/reveal/reveal.vue
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall">
|
||||||
|
<funnelHeader ref="funnelHeader" />
|
||||||
|
<h1>Reveal Confetti Page Placeholder</h1>
|
||||||
|
<funnelFooter ref="funnelFooter" @back-clicked="backButtonAction" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Components
|
||||||
|
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
||||||
|
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import {storeMutations} from "@/constants/store-mutations";
|
||||||
|
import {storeActions} from "@/constants/store-actions";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "quote",
|
||||||
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
// Call APIs
|
||||||
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
|
||||||
|
// Settle promises and get results
|
||||||
|
const promiseResultMap = [{
|
||||||
|
resultKey: "cmsContent",
|
||||||
|
promise: cmsContentPromise,
|
||||||
|
}, ];
|
||||||
|
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
|
||||||
|
// Call the "next" function to complete the transition to this page.
|
||||||
|
next((vm) => {
|
||||||
|
vm.$refs.funnelHeader.initializeComponent(
|
||||||
|
resultMap.cmsContent.FunnelHeaderWidget
|
||||||
|
);
|
||||||
|
vm.$refs.funnelFooter.initializeComponent(
|
||||||
|
resultMap.cmsContent.FunnelFooterWidget
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
backButtonAction() {
|
||||||
|
// route to move backwards
|
||||||
|
this.$router.navigate(
|
||||||
|
this.navigationScenarios.CLICKED_BACK,
|
||||||
|
this.$route
|
||||||
|
);
|
||||||
|
},
|
||||||
|
arePagePrerequisitesValid() {
|
||||||
|
return store.getters.lineItems.glassParts !== null;
|
||||||
|
},
|
||||||
|
resetDependentState() {
|
||||||
|
// Set
|
||||||
|
store.commit(storeMutations.UPDATE_PARTS, null);
|
||||||
|
|
||||||
|
// Invokes
|
||||||
|
store.dispatch(storeActions.RESET_PARTS_AND_DEPS);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
funnelHeader,
|
||||||
|
funnelFooter,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -2,82 +2,81 @@ import { shallowMount } from "@vue/test-utils";
|
||||||
import damageLocationQuestion from "@/layouts/vehicle-damage/damage-location-question/damage-location-question";
|
import damageLocationQuestion from "@/layouts/vehicle-damage/damage-location-question/damage-location-question";
|
||||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
jest.mock("@/store", () => { return {}; }, {virtual: true});
|
jest.mock("@/store", () => { return {}; }, { virtual: true });
|
||||||
|
|
||||||
describe("damage-location-question.vue", () => {
|
describe("damage-location-question.vue", () => {
|
||||||
test("Selected location option is emitted upon selection.", async () => {
|
test("Selected location option is emitted upon selection.", async () => {
|
||||||
|
|
||||||
//Arrange
|
//Arrange
|
||||||
const { wrapper } = setupMocks({ modelValueProp: ["Windshield"] });
|
const { wrapper } = setupMocks({ modelValueProp: ["Windshield"] });
|
||||||
const locationToSelect = ["Backseat"];
|
const locationToSelect = ["Backseat"];
|
||||||
|
|
||||||
//Act
|
//Act
|
||||||
wrapper.setValue({ modelValue: locationToSelect });
|
wrapper.setValue({ modelValue: locationToSelect });
|
||||||
await wrapper.vm.$nextTick();
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{modelValue: ["Backseat"]}]);
|
expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ modelValue: ["Backseat"] }]);
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("damage-location-question.vue", () => {
|
test("Answers to display filtered by data from api.", async () => {
|
||||||
test("Answers to display filtered by data from api.", async () => {
|
|
||||||
|
//Arrange
|
||||||
//Arrange
|
const { wrapper, cmsContent, damageOptions } = setupMocks({
|
||||||
const { wrapper, cmsContent, damageOptions } = setupMocks({ dataFromStoreApi: {
|
dataFromStoreApi: {
|
||||||
driverSideOptions: {
|
driverSideOptions: {
|
||||||
availableReplacementOptions: ['Quarter', 'Front']
|
availableReplacementOptions: ['Quarter', 'Front']
|
||||||
},
|
},
|
||||||
windshieldOptions: {
|
windshieldOptions: {
|
||||||
availableReplacementOptions: ['Single']
|
availableReplacementOptions: ['Single']
|
||||||
},
|
},
|
||||||
backGlassOptions: {
|
backGlassOptions: {
|
||||||
availableReplacementOptions: []
|
availableReplacementOptions: []
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
//Act
|
|
||||||
damageLocationQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, damageOptions, "car-group");
|
|
||||||
|
|
||||||
//Assert
|
|
||||||
expect(wrapper.vm.answersToDisplay).toStrictEqual([ { Name: 'Windshield' }, { Name: 'SideDoor' } ])
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
damageLocationQuestion.methods.initializeComponent.call(wrapper.vm, cmsContent, damageOptions, "car-group");
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.answersToDisplay).toStrictEqual([{ Name: 'Windshield' }, { Name: 'SideDoor' }])
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupMocks({
|
||||||
|
modelValueProp = ["Windshield", "SideDoor"],
|
||||||
|
isMultiSelect = false,
|
||||||
|
groupName = "damageQuestion",
|
||||||
|
cmsQuestionText = "CMS text goes here",
|
||||||
|
cmsAnswers = [{ Name: "car-Windshield" }, { Name: "car-SideDoor" }, { Name: "car-RearWindow" }],
|
||||||
|
dataFromStoreApi = [],
|
||||||
|
}) {
|
||||||
|
|
||||||
|
//Mock store
|
||||||
|
store.dispatch = jest.fn(() => dataFromStoreApi);
|
||||||
|
store.getters = { vehicle: { year: 2019, make: 'honda', model: 'civc', style: '2 Door', category: 'CAR' } };
|
||||||
|
const mountOptions = getMountOptions({
|
||||||
|
store: {
|
||||||
|
dispatch: store.dispatch,
|
||||||
|
getters: store.getters,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
function setupMocks({
|
//Mock props
|
||||||
modelValueProp = ["Windshield", "SideDoor"],
|
mountOptions.propsData = {
|
||||||
isMultiSelect = false,
|
modelValue: modelValueProp,
|
||||||
groupName = "damageQuestion",
|
isMultiSelect: isMultiSelect,
|
||||||
cmsQuestionText = "CMS text goes here",
|
};
|
||||||
cmsAnswers = [{Name: "car-Windshield"}, {Name: "car-SideDoor"}, {Name: "car-RearWindow"}],
|
|
||||||
dataFromStoreApi = [],
|
const wrapper = shallowMount(damageLocationQuestion, mountOptions);
|
||||||
}) {
|
|
||||||
|
//Mock CMS content
|
||||||
//Mock store
|
const cmsContent = {
|
||||||
store.dispatch = jest.fn(() => dataFromStoreApi);
|
groupName: groupName,
|
||||||
store.getters = { vehicle: {year: 2019, make: 'honda', model: 'civc', style: '2 Door', category: 'CAR'} };
|
QuestionText: cmsQuestionText,
|
||||||
const mountOptions = getMountOptions({
|
Answers: cmsAnswers,
|
||||||
store: {
|
};
|
||||||
dispatch: store.dispatch,
|
const damageOptions = dataFromStoreApi;
|
||||||
getters: store.getters,
|
return { wrapper, cmsContent, damageOptions };
|
||||||
},
|
}
|
||||||
});
|
|
||||||
|
|
||||||
//Mock props
|
|
||||||
mountOptions.propsData = {
|
|
||||||
modelValue: modelValueProp,
|
|
||||||
isMultiSelect: isMultiSelect,
|
|
||||||
};
|
|
||||||
|
|
||||||
const wrapper = shallowMount(damageLocationQuestion, mountOptions);
|
|
||||||
|
|
||||||
//Mock CMS content
|
|
||||||
const cmsContent = {
|
|
||||||
groupName: groupName,
|
|
||||||
QuestionText: cmsQuestionText,
|
|
||||||
Answers: cmsAnswers,
|
|
||||||
};
|
|
||||||
const damageOptions = dataFromStoreApi;
|
|
||||||
return { wrapper, cmsContent, damageOptions };
|
|
||||||
}
|
|
||||||
|
|
@ -17,6 +17,7 @@ import { mount, flushPromises } from "@vue/test-utils";
|
||||||
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
import { nextTick } from "vue";
|
import { nextTick } from "vue";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
import { storeMutations } from "@/constants/store-mutations";
|
||||||
import store from "@/store";
|
import store from "@/store";
|
||||||
import { validate } from "vee-validate";
|
import { validate } from "vee-validate";
|
||||||
|
|
||||||
|
|
@ -148,28 +149,6 @@ describe("vehicle-damage.vue", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("vehicle-damage.vue", () => {
|
|
||||||
test("Call invalidation, ResetPartsAndDeps should be called", async () => {
|
|
||||||
|
|
||||||
//Arrange
|
|
||||||
const { wrapper } = setupMocks({});
|
|
||||||
|
|
||||||
//Act
|
|
||||||
vehicleDamage.beforeRouteEnter.call(
|
|
||||||
wrapper.vm,
|
|
||||||
{ query: { fmgPage: "vehicle-damage" } },
|
|
||||||
undefined,
|
|
||||||
(c) => c(wrapper.vm)
|
|
||||||
);
|
|
||||||
|
|
||||||
wrapper.vm.resetDependentState();
|
|
||||||
|
|
||||||
//Assert
|
|
||||||
expect(store.dispatch).toBeCalledWith(storeActions.RESET_PARTS_AND_DEPS)
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("vehicle-damage.vue", () => {
|
describe("vehicle-damage.vue", () => {
|
||||||
test("BackButtonAction triggers a router.navigate change", async () => {
|
test("BackButtonAction triggers a router.navigate change", async () => {
|
||||||
|
|
||||||
|
|
@ -192,6 +171,326 @@ describe("vehicle-damage.vue", () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("Replace several pieces of glass on ForwardButtonAction triggers a router.navigateAfterSave and saves selections to store", async () => {
|
||||||
|
//Arrange
|
||||||
|
const partsData = {
|
||||||
|
partsOrQuestions: [{
|
||||||
|
glassName: "Single",
|
||||||
|
glassLocation: "Windshield",
|
||||||
|
parts: null,
|
||||||
|
partQuestions: [{
|
||||||
|
questionSequence: 1,
|
||||||
|
questionText: "Is your vehicle equipped with a heated steering wheel?",
|
||||||
|
answers: [{
|
||||||
|
answerText: "Yes",
|
||||||
|
nextQuestionSequence: null,
|
||||||
|
answerResult: "FW04957"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
answerText: "No",
|
||||||
|
nextQuestionSequence: 2,
|
||||||
|
answerResult: ""
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
questionSequence: 2,
|
||||||
|
questionText: "Is your vehicle equipped with a remote start?",
|
||||||
|
answers: [{
|
||||||
|
answerText: "Yes",
|
||||||
|
nextQuestionSequence: null,
|
||||||
|
answerResult: "FW04181"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
answerText: "No",
|
||||||
|
nextQuestionSequence: null,
|
||||||
|
answerResult: "FW04179"
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
}]
|
||||||
|
};
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
pageHeaderWidgetHeaderText: "",
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: { navigateAfterSave: jest.fn(), },
|
||||||
|
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
|
||||||
|
store: {
|
||||||
|
getters: {
|
||||||
|
vehicle: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Windshield", "SideDoor", "RearWindow"];
|
||||||
|
wrapper.vm.selectedWindshieldOptions = {
|
||||||
|
selectedWindshieldChipCount : null,
|
||||||
|
selectedWindshieldReplaceOptions : ["Single"],
|
||||||
|
selectedWindshieldDamageType: ["Replace"]
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapper.vm.sideDoorOptionsData = {
|
||||||
|
selectedDoorSides: ["DriverSide", "PassengerSide"],
|
||||||
|
selectedDriverSideReplaceOptions: ["Back"],
|
||||||
|
selectedPassengerSideReplaceOptions: ["Quarter"]
|
||||||
|
};
|
||||||
|
|
||||||
|
wrapper.vm.selectedRearReplaceOptions = ["Stationary"];
|
||||||
|
|
||||||
|
const expectedGlassToReplace = [{location: "Windshield", name: "Single"}, {location: "Driver", name: "Back"},
|
||||||
|
{location: "Passenger", name: "Quarter"}, {location: "Rear", name: "Stationary"}];
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, false);
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_GLASS_TO_REPLACE, expectedGlassToReplace);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("Windshield replace with single part on ForwardButtonAction triggers a router.navigateAfterSave and saves selections to store", async () => {
|
||||||
|
//Arrange
|
||||||
|
const partsData = { partsOrQuestions: [
|
||||||
|
{
|
||||||
|
glassLocation: "Windshield",
|
||||||
|
glassName: "Single",
|
||||||
|
partQuestions: null,
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
color: "Green Tint, Green Shade",
|
||||||
|
description: "rain sensor, solar",
|
||||||
|
partNumber: "FW02728GGYN",
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
requiresRecalibration: false
|
||||||
|
}
|
||||||
|
]}]};
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
pageHeaderWidgetHeaderText: "",
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: { navigateAfterSave: jest.fn(), },
|
||||||
|
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
|
||||||
|
store: {
|
||||||
|
getters: {
|
||||||
|
vehicle: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Windshield"];
|
||||||
|
wrapper.vm.selectedWindshieldOptions = {
|
||||||
|
selectedWindshieldChipCount : null,
|
||||||
|
selectedWindshieldReplaceOptions : ["Single"],
|
||||||
|
selectedWindshieldDamageType: ["Replace"]
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedGlassToReplace = [{location: "Windshield", name: "Single"},];
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, false);
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_GLASS_TO_REPLACE, expectedGlassToReplace);
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_PARTS, partsData.partsOrQuestions[0].parts);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("Windshield replace with multiple parts on ForwardButtonAction triggers a router.navigateAfterSave and saves selections to store", async () => {
|
||||||
|
//Arrange
|
||||||
|
const partsData = { partsOrQuestions: [
|
||||||
|
{
|
||||||
|
glassLocation: "Windshield",
|
||||||
|
glassName: "Single",
|
||||||
|
partQuestions: null,
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
color: "Green Tint, Green Shade",
|
||||||
|
description: "rain sensor, solar",
|
||||||
|
partNumber: "FW02728GGYN",
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
requiresRecalibration: false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
color: "Green Tint, Green Shade",
|
||||||
|
description: "rain sensor, solar, hydrophobic coating",
|
||||||
|
partNumber: "FW02760GGYN",
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
requiresRecalibration: false
|
||||||
|
}
|
||||||
|
]},
|
||||||
|
{
|
||||||
|
glassName: "Stationary",
|
||||||
|
glassLocation: "Rear",
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
partNumber: "DB09626GTYN",
|
||||||
|
description: "heated glass, solar, antenna",
|
||||||
|
color: "Green Tint",
|
||||||
|
requiresRecalibration: false,
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
childParts: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
partNumber: "DB09821GTYN",
|
||||||
|
description: "heated glass, solar, antenna, onstar",
|
||||||
|
color: "Green Tint",
|
||||||
|
requiresRecalibration: false,
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
childParts: null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"partQuestions": null
|
||||||
|
}
|
||||||
|
]};
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
pageHeaderWidgetHeaderText: "",
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: { navigateAfterSave: jest.fn(), },
|
||||||
|
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
|
||||||
|
store: {
|
||||||
|
getters: {
|
||||||
|
vehicle: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Windshield"];
|
||||||
|
wrapper.vm.selectedWindshieldOptions = {
|
||||||
|
selectedWindshieldChipCount : null,
|
||||||
|
selectedWindshieldReplaceOptions : ["Single"],
|
||||||
|
selectedWindshieldDamageType: ["Replace"]
|
||||||
|
};
|
||||||
|
|
||||||
|
const expectedGlassToReplace = [{location: "Windshield", name: "Single"},];
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
|
||||||
|
expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, false);
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_GLASS_TO_REPLACE, expectedGlassToReplace);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("Windshield repair on ForwardButtonAction triggers a router.navigateAfterSave and saves selection to store", async () => {
|
||||||
|
//Arrange
|
||||||
|
const partsData = { partsOrQuestions: []};
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
pageHeaderWidgetHeaderText: "",
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: { navigateAfterSave: jest.fn(), },
|
||||||
|
actionList: [{ actionName: storeActions.GET_PARTS_OR_QUESTIONS, data: partsData, },],
|
||||||
|
store: {
|
||||||
|
getters: {
|
||||||
|
vehicle: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Windshield"];
|
||||||
|
wrapper.vm.selectedWindshieldOptions = {
|
||||||
|
selectedWindshieldChipCount : [2],
|
||||||
|
selectedWindshieldDamageType: ["Repair"]
|
||||||
|
};
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, true);
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_NUMBER_OF_CHIPS, 2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("isWindshieldDamageLocation is true when windshield is selected", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Windshield"];
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isWindshieldDamageLocation).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("isSideDoorDamageLocation is true Side door is selected", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Sidedoor"];
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isSideDoorDamageLocation).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
describe("vehicle-damage.vue", () => {
|
describe("vehicle-damage.vue", () => {
|
||||||
test("isRearWindowDamageLocation is true if Rear Window damage is selected", async () => {
|
test("isRearWindowDamageLocation is true if Rear Window damage is selected", async () => {
|
||||||
|
|
||||||
|
|
@ -210,6 +509,115 @@ describe("vehicle-damage.vue", () => {
|
||||||
|
|
||||||
//Assert
|
//Assert
|
||||||
expect(wrapper.vm.isRearWindowDamageLocation).toEqual(true);
|
expect(wrapper.vm.isRearWindowDamageLocation).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("isWindshieldRepair is true if windshield repair is selected", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Windshield"];
|
||||||
|
wrapper.vm.selectedWindshieldOptions = { selectedWindshieldDamageType: ["Repair"]};
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isWindshieldRepair).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("isWindshieldRepair is false if windshield damage is not selected", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["SideDoor"];
|
||||||
|
wrapper.vm.selectedWindshieldOptions = { selectedWindshieldDamageType: ["Repair"]};
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isWindshieldRepair).toEqual(false);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("isDriverSideReplace is true if side door driver is selected", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Sidedoor"];
|
||||||
|
wrapper.vm.sideDoorOptionsData = { selectedDoorSides: ["DriverSide"]};
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isDriverSideReplace).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("isPassengerSideReplace is true if side door passenger selected", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.selectedDamageLocations = ["Sidedoor"];
|
||||||
|
wrapper.vm.sideDoorOptionsData = { selectedDoorSides: ["PassengerSide"]};
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.isPassengerSideReplace).toEqual(true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("vehicle-damage.vue", () => {
|
||||||
|
test("Call invalidation, ResetPartsAndState should be called", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks({});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleDamage.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-damage" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.resetDependentState();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(store.dispatch).toBeCalledWith(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES)
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@
|
||||||
<funnelHeader ref="funnelHeader" />
|
<funnelHeader ref="funnelHeader" />
|
||||||
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage=false />
|
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage=false />
|
||||||
<funnelSubHeader ref="funnelSubHeader" />
|
<funnelSubHeader ref="funnelSubHeader" />
|
||||||
selectedDamageLocations {{selectedDamageLocations}}
|
|
||||||
isRearWindowDamageLocation {{ isRearWindowDamageLocation }}
|
|
||||||
<Form
|
<Form
|
||||||
@submit="onSubmit"
|
@submit="onSubmit"
|
||||||
@invalid-submit="onInvalidSubmit"
|
@invalid-submit="onInvalidSubmit"
|
||||||
|
|
@ -47,6 +45,7 @@
|
||||||
ref="funnelFooter"
|
ref="funnelFooter"
|
||||||
:isDisabled="!meta.valid"
|
:isDisabled="!meta.valid"
|
||||||
@back-clicked="backButtonAction"
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- KEEP TEMPORARILY FOR TROUBLESHOOTING VALIDATION -->
|
<!-- KEEP TEMPORARILY FOR TROUBLESHOOTING VALIDATION -->
|
||||||
|
|
@ -84,6 +83,8 @@ import baseMixin from "@/mixins/base-mixin";
|
||||||
import { Form, defineRule } from "vee-validate";
|
import { Form, 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 { damageLocationsParts } from "@/constants/damage-locations-parts.js";
|
||||||
|
import { damageLocationsCms } from "@/constants/damage-locations-cms.js";
|
||||||
|
|
||||||
// DEFINE VALIDATION RULES
|
// DEFINE VALIDATION RULES
|
||||||
defineRule("replace-options-required", required(errorMessages.REPLACE_OPTIONS_REQUIRED));
|
defineRule("replace-options-required", required(errorMessages.REPLACE_OPTIONS_REQUIRED));
|
||||||
|
|
@ -142,14 +143,6 @@ export default {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
computed: {
|
|
||||||
isRearWindowDamageLocation() {
|
|
||||||
return this.selectedDamageLocations.some(selectedDamages =>
|
|
||||||
{
|
|
||||||
return selectedDamages.toUpperCase() === "REARWINDOW";
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data(){
|
data(){
|
||||||
return {
|
return {
|
||||||
selectedDamageLocations: [],
|
selectedDamageLocations: [],
|
||||||
|
|
@ -167,8 +160,7 @@ export default {
|
||||||
return store.getters.vehicle.carId !== null;
|
return store.getters.vehicle.carId !== null;
|
||||||
},
|
},
|
||||||
resetDependentState() {
|
resetDependentState() {
|
||||||
// Invokes
|
store.dispatch(storeActions.RESET_PARTS_STATE_AND_DEPENDENCIES);
|
||||||
store.dispatch(storeActions.RESET_PARTS_AND_DEPS);
|
|
||||||
},
|
},
|
||||||
backButtonAction() {
|
backButtonAction() {
|
||||||
// route to move backwards
|
// route to move backwards
|
||||||
|
|
@ -194,7 +186,125 @@ export default {
|
||||||
el && el.focus();
|
el && el.focus();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
async forwardButtonAction() {
|
||||||
|
var windshieldChipCount = this.selectedWindshieldOptions.selectedWindshieldChipCount && this.isWindshieldDamageLocation ?
|
||||||
|
this.selectedWindshieldOptions.selectedWindshieldChipCount[0] : null;
|
||||||
|
|
||||||
|
store.commit(this.storeMutations.UPDATE_IS_REPAIR, this.isWindshieldRepair);
|
||||||
|
|
||||||
|
if (windshieldChipCount){
|
||||||
|
store.commit(this.storeMutations.UPDATE_NUMBER_OF_CHIPS, parseInt(windshieldChipCount));
|
||||||
|
}
|
||||||
|
|
||||||
|
store.commit(this.storeMutations.UPDATE_GLASS_TO_REPLACE, this.selectedGlassToReplace());
|
||||||
|
|
||||||
|
var partsData = await baseMixin.methods.dispatchNonBlockingStoreAction(this.storeActions.GET_PARTS_OR_QUESTIONS,
|
||||||
|
{ carId: store.getters.vehicle.carId, glassArray: this.selectedGlassToReplace()}, false);
|
||||||
|
|
||||||
|
this.navigateForward(partsData);
|
||||||
|
},
|
||||||
|
|
||||||
|
navigateForward(partsData){
|
||||||
|
//found problem questions
|
||||||
|
if (partsData.data.partsOrQuestions.some(pq => pq.partQuestions != null && pq.partQuestions.length > 0)){
|
||||||
|
this.$router.navigateAfterSave(this.navigationScenarios.SELECTED_DAMAGE_WITH_PART_QUESTIONS, this.$route, {}, {}, partsData.data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//found multiple parts for a single glass location (Windshield, Driver, Passenger, Rear)
|
||||||
|
if (partsData.data.partsOrQuestions){
|
||||||
|
var multiParts = false;
|
||||||
|
partsData.data.partsOrQuestions.forEach(pq => {
|
||||||
|
if (pq.parts != null && pq.parts.length > 1){
|
||||||
|
this.$router.navigateAfterSave(this.navigationScenarios.SELECTED_DAMAGE_WITH_MULTIPLE_PARTS, this.$route, {}, {}, partsData.data);
|
||||||
|
multiParts = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (multiParts) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//if not a repair then there should only be 1 part and no problem questions at this point so save the part to the store.
|
||||||
|
if (!this.isWindshieldRepair){
|
||||||
|
store.commit(this.storeMutations.UPDATE_PARTS, partsData.data.partsOrQuestions[0].parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$router.navigateAfterSave(this.navigationScenarios.SELECTED_DAMAGE_WITH_SINGLE_PART, this.$route);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedGlassToReplace() {
|
||||||
|
var selectedGlassToReplace = [];
|
||||||
|
if (this.isWindshieldDamageLocation && !this.isWindshieldRepair){
|
||||||
|
this.selectedWindshieldOptions.selectedWindshieldReplaceOptions.forEach(wsItem => {
|
||||||
|
selectedGlassToReplace.push({ location: damageLocationsParts.WINDSHIELD, name: wsItem});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isDriverSideReplace){
|
||||||
|
this.sideDoorOptionsData.selectedDriverSideReplaceOptions.forEach(driverItem => {
|
||||||
|
selectedGlassToReplace.push({ location: damageLocationsParts.DRIVER, name: driverItem});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isPassengerSideReplace){
|
||||||
|
this.sideDoorOptionsData.selectedPassengerSideReplaceOptions.forEach(passengerItem => {
|
||||||
|
selectedGlassToReplace.push({ location: damageLocationsParts.PASSENGER, name: passengerItem});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.isRearWindowDamageLocation) {
|
||||||
|
this.selectedRearReplaceOptions.forEach(rearItem => {
|
||||||
|
selectedGlassToReplace.push({ location: damageLocationsParts.REAR, name: rearItem});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return selectedGlassToReplace;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
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.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;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
funnelHeader,
|
funnelHeader,
|
||||||
funnelFooter,
|
funnelFooter,
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
:answers="answersFromCms"
|
:answers="answersFromCms"
|
||||||
:groupName="groupName"
|
:groupName="groupName"
|
||||||
buttonType="listButtonHorizontal"
|
buttonType="listButtonHorizontal"
|
||||||
|
useTextForValue
|
||||||
v-model="selectedChipCountValues"
|
v-model="selectedChipCountValues"
|
||||||
:validationRules="validationRules"
|
:validationRules="validationRules"
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -223,8 +223,8 @@ describe("vehicle-make.vue", () => {
|
||||||
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
|
||||||
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
|
||||||
|
|
||||||
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_AND_DEPS)
|
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES)
|
||||||
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_AND_DEPS)
|
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES)
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,8 @@ export default {
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
|
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
|
||||||
|
|
||||||
// Invokes
|
// Invokes
|
||||||
store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
|
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
|
store.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -208,8 +208,8 @@ describe("vehicle-model.vue", () => {
|
||||||
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
|
||||||
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
|
||||||
|
|
||||||
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_AND_DEPS)
|
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES)
|
||||||
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_AND_DEPS)
|
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES)
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -94,8 +94,8 @@ export default {
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
|
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
|
||||||
|
|
||||||
// Invokes
|
// Invokes
|
||||||
store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
|
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
|
store.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,137 @@
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
import glassPartQuestion from "@/layouts/vehicle-parts/glass-part-question/glass-part-question.vue";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
|
jest.mock("@/store", () => { return {}; }, { virtual: true });
|
||||||
|
store.getters = {
|
||||||
|
pageData: jest.fn()
|
||||||
|
};
|
||||||
|
|
||||||
|
const featureListData = {
|
||||||
|
colorAnswersProp: [
|
||||||
|
{ ColorAnswerText: 'Green Tint', FeatureAnswers: [{ FeatureAnswerText: "heated glass, solar, 1 hole", PartNumber: "DB12209GTYN" }] },
|
||||||
|
{ ColorAnswerText: 'Gray Tint Privacy', FeatureAnswers: [{ FeatureAnswerText: "heated glass, solar, 1 hole", PartNumber: "DB12209YPYN" }] }
|
||||||
|
],
|
||||||
|
glassLocationProp: "Rear",
|
||||||
|
glassNameProp: "Stationary",
|
||||||
|
modelValueProp: {}
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("glass-part-question.vue", () => {
|
||||||
|
|
||||||
|
test("Part data passed in, should map data for ButtonQuestion (radio type)", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks(featureListData);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(Object.keys(wrapper.vm.featureListData).length).toBe(2);
|
||||||
|
expect(wrapper.vm.featureListData['Green Tint'][0].Text).toBe("heated glass, solar, 1 hole");
|
||||||
|
expect(wrapper.vm.featureListData['Green Tint'][0].Name).toBe("DB12209GTYN");
|
||||||
|
expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Text).toBe("heated glass, solar, 1 hole");
|
||||||
|
expect(wrapper.vm.featureListData['Gray Tint Privacy'][0].Name).toBe("DB12209YPYN");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Tint mapper, should get tint image by glassLocation and tintColor", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(featureListData);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
const tintSourceImage = wrapper.vm.getTintSourceImage("Rear", "Green Tint");
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(tintSourceImage).toBe("Glass-NoShade-GreenTint.svg");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
test("Tint mapper, should return empty string if no tint map found", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(featureListData);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
const tintSourceImage = wrapper.vm.getTintSourceImage("Rear", "Crazy Rainbow Tint");
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(tintSourceImage).toBe("");
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Should emit updateModelValue, and have correct attributes", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks(featureListData);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
const listCard = await wrapper.findComponent({
|
||||||
|
name: "listCard",
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.setValue({ selectedTint: 'Green Tint' });
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.emitted()["update:modelValue"][0]).toEqual([{ selectedTint: 'Green Tint' }]);
|
||||||
|
expect(listCard.attributes("buttonid")).toBe("Rear-Stationary-Green Tint");
|
||||||
|
expect(listCard.attributes("groupname")).toBe("Rear-Stationary");
|
||||||
|
expect(listCard.attributes("isradio")).toBe("true");
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ResetTintAndPartSelections, should reset data elements ", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
const { wrapper } = setupMocks(featureListData);
|
||||||
|
|
||||||
|
//Act
|
||||||
|
await wrapper.vm.$nextTick();
|
||||||
|
wrapper.setData({ selectedTint: { "Rear-Stationary": 'Green Tint' } });
|
||||||
|
|
||||||
|
expect(wrapper.vm.selectedTint).toStrictEqual({ "Rear-Stationary": 'Green Tint' });
|
||||||
|
|
||||||
|
await wrapper.vm.ResetTintAndPartSelections();
|
||||||
|
expect(wrapper.vm.selectedTint).toStrictEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
function setupMocks({ glassNameProp, glassLocationProp, colorAnswersProp, modelValueProp }) {
|
||||||
|
|
||||||
|
//Mock store
|
||||||
|
store.getters.pageData.mockReturnValueOnce({ partsOrQuestions: {}});
|
||||||
|
store.getters.lineItems = { glassParts: {} }
|
||||||
|
|
||||||
|
const mountOptions = getMountOptions({
|
||||||
|
store: {
|
||||||
|
getters: store.getters,
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
query: {
|
||||||
|
fmgPage: 'vehicle-parts',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
mountOptions.propsData = {
|
||||||
|
glassName: glassNameProp,
|
||||||
|
glassLocation: glassLocationProp,
|
||||||
|
colorAnswers: colorAnswersProp,
|
||||||
|
modelValue: modelValueProp
|
||||||
|
};
|
||||||
|
|
||||||
|
const wrapper = shallowMount(glassPartQuestion, mountOptions);
|
||||||
|
|
||||||
|
return { wrapper };
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
<template>
|
||||||
|
<div class="container">
|
||||||
|
<div class="row">
|
||||||
|
<p class="mb-0">{{ colorQuestionText }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container nested-radio" v-for="(value, name, index) in featureListData" :key="index">
|
||||||
|
|
||||||
|
<div class="row my-2">
|
||||||
|
<div class="col">
|
||||||
|
<listCard v-model="selectedTint[name]" :isRadio="true" :isWide="true" :buttonImage="
|
||||||
|
require(`@/assets/img/tints/${getTintSourceImage(
|
||||||
|
glassLocation,
|
||||||
|
name
|
||||||
|
)}`)
|
||||||
|
" :buttonLabel="name" altText="" :buttonID="`${glassLocation}-${glassName}-${name}`" :groupName="`${glassLocation}-${glassName}`" @isCheckedChanged="ResetTintAndPartSelections()" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<transition name="fade" mode="out-in">
|
||||||
|
<div v-if="
|
||||||
|
selectedTint[name] != undefined &&
|
||||||
|
selectedTint[name].buttonId ===
|
||||||
|
`${glassLocation}-${glassName}-${name}`
|
||||||
|
" class="row my-2" aria-live="polite">
|
||||||
|
<div class="col">
|
||||||
|
<buttonQuestion v-model="selectedPart[glassLocation]" buttonType="radio" class="radioQuestion" :questionText="glassFeatureQuestion" :answers="value" textPosition="text-start" :loaderEnabled="false" :isRequired="true" :groupName="`${glassLocation}-${glassName}-${name}`" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</transition>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Components
|
||||||
|
import listCard from "@/ux-components/list-card/list-card";
|
||||||
|
import buttonQuestion from "@/common-components/button-question/button-question";
|
||||||
|
|
||||||
|
// Supporting files
|
||||||
|
import {
|
||||||
|
getTintImage
|
||||||
|
} from "@/constants/tint-mapper";
|
||||||
|
import {
|
||||||
|
getCustomTransformValue
|
||||||
|
} from "@/constants/dynamictext-mapper";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "glass-part-question",
|
||||||
|
inheritAttrs: false,
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
glassColorQuestion: "",
|
||||||
|
glassFeatureQuestion: "",
|
||||||
|
selectedTint: {}, // v-model for the list card selections
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
glassName: String,
|
||||||
|
glassLocation: String,
|
||||||
|
colorAnswers: Array,
|
||||||
|
modelValue: Object,
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
if (this.modelValue !== undefined) {
|
||||||
|
// Populate button-question model-value if parts data already exists in VueX
|
||||||
|
const alreadyPopulatedPartsData =
|
||||||
|
this.$store.getters.lineItems.glassParts;
|
||||||
|
|
||||||
|
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] = {
|
||||||
|
buttonId: `${this.glassLocation}-${this.glassName}-${tintColor}`,
|
||||||
|
checkValue: "",
|
||||||
|
value: "",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
listCard,
|
||||||
|
buttonQuestion,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
colorQuestionText() {
|
||||||
|
return getCustomTransformValue(
|
||||||
|
this.glassColorQuestion,
|
||||||
|
`${this.glassLocation} ${this.glassName}`
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectedPart: {
|
||||||
|
get: function () {
|
||||||
|
return this.modelValue;
|
||||||
|
},
|
||||||
|
set: function (newValue) {
|
||||||
|
this.$emit("update:modelValue", newValue);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// Creates a map of the feature list data in the correct Name/Value
|
||||||
|
// format for the button-question component.
|
||||||
|
featureListData() {
|
||||||
|
const tintMapByColor = this.colorAnswers.reduce((arr, item) => {
|
||||||
|
// Create the key
|
||||||
|
const itemColor = item.ColorAnswerText;
|
||||||
|
arr[itemColor] = arr[itemColor] || [];
|
||||||
|
|
||||||
|
// Map the data to Name/Text object for ButtonQuestion
|
||||||
|
const mappedItem = item.FeatureAnswers.reduce((featureArr, item) => {
|
||||||
|
featureArr["Text"] = item.FeatureAnswerText; // Display to User
|
||||||
|
featureArr["Name"] = item.PartNumber; // Backing Value
|
||||||
|
|
||||||
|
return featureArr;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
// Add onto the final object
|
||||||
|
arr[itemColor].push(mappedItem);
|
||||||
|
|
||||||
|
return arr;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
return tintMapByColor;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initializeComponent(cmsContent) {
|
||||||
|
this.glassColorQuestion = cmsContent.ColorQuestionWidget.QuestionText;
|
||||||
|
this.glassFeatureQuestion = cmsContent.FeatureQuestionWidget.QuestionText;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Gets tint images based on the glass type, and tint name.
|
||||||
|
// Returns an empty string if the src or object is undefined.
|
||||||
|
getTintSourceImage(glassLocation, tintColor) {
|
||||||
|
const tintSourceObject = getTintImage(glassLocation, tintColor);
|
||||||
|
|
||||||
|
if (tintSourceObject === undefined || tintSourceObject.src == undefined) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return tintSourceObject.src;
|
||||||
|
},
|
||||||
|
|
||||||
|
// 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 = {};
|
||||||
|
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
|
||||||
|
const partsData = this.$store.getters.pageData(this.$route.query.fmgPage);
|
||||||
|
|
||||||
|
Object.keys(partsData.partsOrQuestions).forEach((key) => {
|
||||||
|
const currentGlassSelection = partsData.partsOrQuestions[key];
|
||||||
|
|
||||||
|
if (currentGlassSelection.glassName === this.glassName && currentGlassSelection.glassLocation === this.glassLocation) {
|
||||||
|
if (currentGlassSelection.parts.length === 1) {
|
||||||
|
this.selectedPart = { [currentGlassSelection.glassLocation]: [currentGlassSelection.parts[0].partNumber]};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss">
|
||||||
|
.nested-radio {
|
||||||
|
.ui-radio {
|
||||||
|
flex-direction: column;
|
||||||
|
margin: 0.25rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
403
src/layouts/vehicle-parts/vehicle-parts.spec.js
Normal file
|
|
@ -0,0 +1,403 @@
|
||||||
|
// Components
|
||||||
|
import vehicleParts from "@/layouts/vehicle-parts/vehicle-parts.vue";
|
||||||
|
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
||||||
|
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
|
||||||
|
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||||
|
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
import glassPartQuestion from "@/layouts/vehicle-parts/glass-part-question/glass-part-question";
|
||||||
|
|
||||||
|
// Supporting Files
|
||||||
|
import { settleAllPromises } from "@/helpers/layout-helper.js";
|
||||||
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
import { shallowMount } from "@vue/test-utils";
|
||||||
|
import { getMountOptions } from "@/helpers/unit-test-helper.js";
|
||||||
|
import { nextTick } from "vue";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
|
// Mock our module for promises.
|
||||||
|
jest.mock("@/helpers/layout-helper.js", () => ({
|
||||||
|
settleAllPromises: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Mock fetchCmsContentForPage
|
||||||
|
jest.mock("@/helpers/cms-content-helper", () => ({
|
||||||
|
fetchCmsContentForPage: jest.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Mock store
|
||||||
|
jest.mock("@/store", () => { return {}; }, { virtual: true });
|
||||||
|
|
||||||
|
store.getters = {
|
||||||
|
pageData: jest.fn(),
|
||||||
|
damage: {
|
||||||
|
isRepair: false
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const basePartResponse = {
|
||||||
|
partsOrQuestions: [
|
||||||
|
{
|
||||||
|
glassName: "Stationary",
|
||||||
|
glassLocation: "Rear",
|
||||||
|
parts: [
|
||||||
|
{
|
||||||
|
partNumber: "DB12209GTYN",
|
||||||
|
description: "heated glass, solar, 1 hole",
|
||||||
|
color: "Green Tint",
|
||||||
|
requiresRecalibration: false,
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
childParts: null
|
||||||
|
},
|
||||||
|
{
|
||||||
|
partNumber: "DB12209YPYNOEM",
|
||||||
|
description: "heated glass, solar, 1 hole",
|
||||||
|
color: "Gray Tint Privacy",
|
||||||
|
requiresRecalibration: false,
|
||||||
|
requiresCapabilityQuestions: false,
|
||||||
|
childParts: null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
partQuestions: null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
describe("vehicle-parts.vue", () => {
|
||||||
|
|
||||||
|
test("Page header is initialized with api data", async (done) => {
|
||||||
|
//Arrange
|
||||||
|
store.getters.pageData.mockReturnValueOnce(basePartResponse);
|
||||||
|
store.getters.lineItems = { glassParts: {} }
|
||||||
|
|
||||||
|
const pageHeaderWidgetHeaderText = "Select Parts";
|
||||||
|
const { wrapper, apiPromise } = setupMocks(
|
||||||
|
{
|
||||||
|
pageHeaderWidgetHeaderText: pageHeaderWidgetHeaderText,
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: {
|
||||||
|
navigateAfterSave: jest.fn()
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
query: {
|
||||||
|
fmgPage: 'vehicle-parts',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
getters: store.getters
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleParts.beforeRouteEnter.call(wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-parts" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
apiPromise.finally(() => {
|
||||||
|
expect(funnelSubHeader.methods.initializeComponent).toHaveBeenCalledWith(pageHeaderWidgetHeaderText);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Page logo image is initialized with api data", async (done) => {
|
||||||
|
//Arrange
|
||||||
|
const SiteHeaderWidget = {
|
||||||
|
LogoImage:
|
||||||
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
||||||
|
};
|
||||||
|
|
||||||
|
store.getters.pageData.mockReturnValueOnce(basePartResponse);
|
||||||
|
store.getters.lineItems = { glassParts: {} }
|
||||||
|
|
||||||
|
const { wrapper, apiPromise } = setupMocks(
|
||||||
|
{
|
||||||
|
SiteHeaderWidget: SiteHeaderWidget,
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: {
|
||||||
|
navigateAfterSave: jest.fn()
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
query: {
|
||||||
|
fmgPage: 'vehicle-parts',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
getters: store.getters
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleParts.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-parts" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
apiPromise.finally(() => {
|
||||||
|
expect(funnelHeader.methods.initializeComponent).toHaveBeenCalledWith(SiteHeaderWidget);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Vehicle image is initialized with api data", async (done) => {
|
||||||
|
//Arrange
|
||||||
|
const VehicleBannerWidget = {
|
||||||
|
GenericVehicleImage:
|
||||||
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||||
|
};
|
||||||
|
|
||||||
|
store.getters.pageData.mockReturnValue(basePartResponse);
|
||||||
|
store.getters.lineItems = { glassParts: {} }
|
||||||
|
|
||||||
|
const { wrapper, apiPromise } = setupMocks(
|
||||||
|
{
|
||||||
|
VehicleBannerWidget: VehicleBannerWidget,
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: {
|
||||||
|
navigateAfterSave: jest.fn()
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
query: {
|
||||||
|
fmgPage: 'vehicle-parts',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
getters: store.getters
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleParts.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-parts" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
apiPromise.finally(() => {
|
||||||
|
expect(vehicleBanner.methods.initializeComponent).toHaveBeenCalledWith(VehicleBannerWidget);
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
test("PageData / isRepair populated in Vuex. arePagePrerequisitesValid should be true ", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
store.getters.pageData.mockReturnValueOnce(basePartResponse);
|
||||||
|
store.getters.lineItems = { glassParts: {} }
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: {
|
||||||
|
navigateAfterSave: jest.fn()
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
query: {
|
||||||
|
fmgPage: 'vehicle-parts',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
getters: store.getters
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleParts.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-parts" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
let arePagePrerequisitesValid = wrapper.vm.arePagePrerequisitesValid();
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(arePagePrerequisitesValid).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test("Initial data, should populate this.glassParts", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
store.getters.pageData.mockReturnValueOnce(basePartResponse);
|
||||||
|
store.getters.lineItems = { glassParts: { 0: { partNumber: 'DB12209YPYNOEM'} } }
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: {
|
||||||
|
navigateAfterSave: jest.fn()
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
query: {
|
||||||
|
fmgPage: 'vehicle-parts',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
getters: store.getters
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleParts.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-parts" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.glassParts).toEqual({ "Rear-Stationary": { "Rear": ['DB12209YPYNOEM'] } });
|
||||||
|
});
|
||||||
|
|
||||||
|
test("BackButtonAction triggers a router.navigate change", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
store.getters.pageData.mockReturnValueOnce(basePartResponse);
|
||||||
|
store.getters.lineItems = { glassParts: {} }
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: {
|
||||||
|
navigateAfterSave: jest.fn(),
|
||||||
|
navigate: jest.fn()
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
query: {
|
||||||
|
fmgPage: 'vehicle-parts',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
getters: store.getters
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleParts.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-parts" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
wrapper.vm.backButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigate).toHaveBeenCalled();
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
test("ForwardButtonAction triggers a router.navigate change and saves selected parts to store", async () => {
|
||||||
|
|
||||||
|
//Arrange
|
||||||
|
store.getters.pageData.mockReturnValueOnce(basePartResponse);
|
||||||
|
store.getters.lineItems = { glassParts: {} }
|
||||||
|
|
||||||
|
|
||||||
|
store.commit = jest.fn();
|
||||||
|
|
||||||
|
const { wrapper } = setupMocks({
|
||||||
|
mountOptionsMockData: {
|
||||||
|
router: {
|
||||||
|
navigateAfterSave: jest.fn(),
|
||||||
|
navigate: jest.fn()
|
||||||
|
},
|
||||||
|
route: {
|
||||||
|
query: {
|
||||||
|
fmgPage: 'vehicle-parts',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
store: {
|
||||||
|
getters: store.getters,
|
||||||
|
commit: store.commit
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
wrapper.setData({ glassParts: { "Rear-Stationary": { "Rear": ['DB12209YPYNOEM'] } } });
|
||||||
|
|
||||||
|
//Act
|
||||||
|
vehicleParts.beforeRouteEnter.call(
|
||||||
|
wrapper.vm,
|
||||||
|
{ query: { fmgPage: "vehicle-parts" } },
|
||||||
|
undefined,
|
||||||
|
(c) => c(wrapper.vm)
|
||||||
|
);
|
||||||
|
|
||||||
|
await wrapper.vm.forwardButtonAction();
|
||||||
|
|
||||||
|
//Assert
|
||||||
|
expect(wrapper.vm.$router.navigateAfterSave).toHaveBeenCalled();
|
||||||
|
// expect(wrapper.vm.selectedGlassToReplace()).toEqual(expectedGlassToReplace);
|
||||||
|
// expect(store.commit).toBeCalledWith(storeMutations.UPDATE_IS_REPAIR, false);
|
||||||
|
// expect(store.commit).toBeCalledWith(storeMutations.UPDATE_GLASS_TO_REPLACE, expectedGlassToReplace);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function setupMocks({ pageHeaderWidgetHeaderText = {}, mountOptionsMockData = {} }) {
|
||||||
|
//Mock api responses
|
||||||
|
const apiResponses = {
|
||||||
|
cmsContent: {
|
||||||
|
FunnelSubHeaderWidget: pageHeaderWidgetHeaderText,
|
||||||
|
VehicleBannerWidget: {
|
||||||
|
GenericVehicleImage:
|
||||||
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/blurred-image.jpg?sfvrsn=a6ce3034_3",
|
||||||
|
},
|
||||||
|
FunnelHeaderWidget: {
|
||||||
|
LogoImage:
|
||||||
|
"https://digitalconsumercms-dev.safelite.com/images/default-source/default-album/safelite-logo.svg?sfvrsn=45e7ed06_3",
|
||||||
|
},
|
||||||
|
ColorQuestionWidget: 'Please choose your rear window tint color',
|
||||||
|
FeatureQuestionWidget: 'Ok no choose features',
|
||||||
|
AlertWidget: {
|
||||||
|
BodyText: 'Please choose your tint color',
|
||||||
|
HeadlineText: 'Just a few more steps to go',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const apiPromise = Promise.resolve(apiResponses);
|
||||||
|
|
||||||
|
settleAllPromises.mockImplementation(() => apiPromise);
|
||||||
|
fetchCmsContentForPage.mockImplementation(() => Promise.resolve());
|
||||||
|
|
||||||
|
//Mock damage initialize methods
|
||||||
|
funnelHeader.methods = { initializeComponent: jest.fn() };
|
||||||
|
vehicleBanner.methods = { initializeComponent: jest.fn() };
|
||||||
|
funnelSubHeader.methods = { initializeComponent: jest.fn() };
|
||||||
|
funnelFooter.methods = { initializeComponent: jest.fn() }
|
||||||
|
|
||||||
|
const mountOptions = getMountOptions(mountOptionsMockData,);
|
||||||
|
const wrapper = shallowMount(vehicleParts, mountOptions);
|
||||||
|
|
||||||
|
const funnelHeaderWrapper = wrapper.findComponent({ name: "funnelHeader" });
|
||||||
|
funnelHeaderWrapper.vm.initializeComponent = funnelHeader.methods.initializeComponent;
|
||||||
|
|
||||||
|
const vehicleBannerWrapper = wrapper.findComponent({ name: "vehicleBanner" });
|
||||||
|
vehicleBannerWrapper.vm.initializeComponent = vehicleBanner.methods.initializeComponent;
|
||||||
|
|
||||||
|
const funnelSubHeaderWrapper = wrapper.findComponent({ name: "funnelSubHeader", });
|
||||||
|
funnelSubHeaderWrapper.vm.initializeComponent = funnelSubHeader.methods.initializeComponent;
|
||||||
|
|
||||||
|
const funnelFooterWrapper = wrapper.findComponent({ name: "funnelFooter", });
|
||||||
|
funnelFooterWrapper.vm.initializeComponent = funnelFooter.methods.initializeComponent;
|
||||||
|
|
||||||
|
const partQuestionRearWrapper = wrapper.findComponent({ name: "glassPartQuestion", });
|
||||||
|
partQuestionRearWrapper.vm.initializeComponent = glassPartQuestion.methods.initializeComponent;
|
||||||
|
|
||||||
|
return { wrapper, apiPromise };
|
||||||
|
}
|
||||||
230
src/layouts/vehicle-parts/vehicle-parts.vue
Normal file
|
|
@ -0,0 +1,230 @@
|
||||||
|
<template>
|
||||||
|
<div class="container-fluid shadow rounded-3 p-2 position-relative make-tall">
|
||||||
|
<funnelHeader ref="funnelHeader" />
|
||||||
|
<vehicleBanner ref="vehicleBanner" :displayGenericVehicleImage="false" />
|
||||||
|
<funnelSubHeader ref="funnelSubHeader" />
|
||||||
|
<div class="container-fluid prevent-squish my-5">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<alert
|
||||||
|
class="rounded border-0 shadow-sm"
|
||||||
|
alertClass="alert-warning"
|
||||||
|
:alertHeadline="alertWidgetData.headline"
|
||||||
|
:alertCopy="alertWidgetData.copy"
|
||||||
|
:isDismissible="false"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-for="(item, i) in PartsForQuestions" :key="i">
|
||||||
|
<!-- Render horizontal lines if there is multi-glass (aka if i > 0) -->
|
||||||
|
<div class="container-fluid">
|
||||||
|
<hr v-if="i > 0" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<glassPartQuestion
|
||||||
|
:ref="`${RefPrefix}-${item.glassLocation}-${item.glassName}`"
|
||||||
|
v-model="glassParts[item.glassLocation + '-' + item.glassName]"
|
||||||
|
:glassLocation="item.glassLocation"
|
||||||
|
:glassName="item.glassName"
|
||||||
|
:colorAnswers="item.colorAnswers"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<funnelFooter
|
||||||
|
ref="funnelFooter"
|
||||||
|
@back-clicked="backButtonAction"
|
||||||
|
@ForwardClicked="forwardButtonAction"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
// Components
|
||||||
|
import glassPartQuestion from "@/layouts/vehicle-parts/glass-part-question/glass-part-question";
|
||||||
|
import funnelHeader from "@/common-components/funnel-header/funnel-header";
|
||||||
|
import vehicleBanner from "@/common-components/vehicle-banner/vehicle-banner";
|
||||||
|
import funnelSubHeader from "@/common-components/funnel-sub-header/funnel-sub-header";
|
||||||
|
import funnelFooter from "@/common-components/funnel-footer/funnel-footer";
|
||||||
|
import alert from "@/ux-components/alert/alert";
|
||||||
|
// Supporting Files
|
||||||
|
import { fetchCmsContentForPage } from "@/helpers/cms-content-helper";
|
||||||
|
import { settleAllPromises } from "@/helpers/layout-helper";
|
||||||
|
import { fmgPageValues } from "@/router/router-constants/fmgPage-values";
|
||||||
|
import { storeMutations } from "@/constants/store-mutations";
|
||||||
|
import store from "@/store";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: "vehicle-parts",
|
||||||
|
async beforeRouteEnter(to, from, next) {
|
||||||
|
// Call APIs
|
||||||
|
const cmsContentPromise = fetchCmsContentForPage(to.query.fmgPage);
|
||||||
|
// Settle promises and get results
|
||||||
|
const promiseResultMap = [
|
||||||
|
{
|
||||||
|
resultKey: "cmsContent",
|
||||||
|
promise: cmsContentPromise,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const resultMap = await settleAllPromises(promiseResultMap);
|
||||||
|
// Call the "next" function to complete the transition to this page.
|
||||||
|
next((vm) => {
|
||||||
|
vm.$refs.funnelHeader.initializeComponent(
|
||||||
|
resultMap.cmsContent.FunnelHeaderWidget
|
||||||
|
);
|
||||||
|
vm.$refs.vehicleBanner.initializeComponent(
|
||||||
|
resultMap.cmsContent.VehicleBannerWidget
|
||||||
|
);
|
||||||
|
vm.$refs.funnelSubHeader.initializeComponent(
|
||||||
|
resultMap.cmsContent.FunnelSubHeaderWidget
|
||||||
|
);
|
||||||
|
vm.$refs.funnelFooter.initializeComponent(
|
||||||
|
resultMap.cmsContent.FunnelFooterWidget
|
||||||
|
);
|
||||||
|
|
||||||
|
// Glass Part Question dynamic component
|
||||||
|
|
||||||
|
Object.keys(vm.$refs)
|
||||||
|
.filter((r) => r.includes(vm.RefPrefix) && vm.$refs[r][0] !== undefined)
|
||||||
|
.forEach((c) =>
|
||||||
|
vm.$refs[c][0].initializeComponent({
|
||||||
|
ColorQuestionWidget: resultMap.cmsContent.ColorQuestionWidget,
|
||||||
|
FeatureQuestionWidget: resultMap.cmsContent.FeatureQuestionWidget,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set alertData for the page alert. These use props so we don't call
|
||||||
|
// initializeComponent here.
|
||||||
|
vm.alertWidgetData = {
|
||||||
|
copy: resultMap.cmsContent.AlertWidget.BodyText,
|
||||||
|
headline: resultMap.cmsContent.AlertWidget.HeadlineText,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
glassParts: {},
|
||||||
|
alertWidgetData: Object,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {
|
||||||
|
glassPartQuestion,
|
||||||
|
funnelHeader,
|
||||||
|
vehicleBanner,
|
||||||
|
funnelSubHeader,
|
||||||
|
funnelFooter,
|
||||||
|
alert,
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
PartsForQuestions() {
|
||||||
|
const partsData = this.$store.getters.pageData(this.$route.query.fmgPage);
|
||||||
|
const alreadyPopulatedPartsData =
|
||||||
|
this.$store.getters.lineItems.glassParts === null
|
||||||
|
? {}
|
||||||
|
: this.$store.getters.lineItems.glassParts;
|
||||||
|
|
||||||
|
// Map API result data, to vehicle-parts data structure
|
||||||
|
const mappedData = 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) => {
|
||||||
|
const partNumber = alreadyPopulatedPartsData[key].partNumber;
|
||||||
|
g.parts.forEach((p) => {
|
||||||
|
if (p.partNumber === partNumber) {
|
||||||
|
this.glassParts[g.glassLocation + "-" + g.glassName] = {
|
||||||
|
[g.glassLocation]: [partNumber],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
glassName: g.glassName,
|
||||||
|
glassLocation: g.glassLocation,
|
||||||
|
colorAnswers: g.parts.reduce((arr, p) => {
|
||||||
|
arr.push({
|
||||||
|
ColorAnswerText: p.color,
|
||||||
|
FeatureAnswers: [
|
||||||
|
{
|
||||||
|
FeatureAnswerText:
|
||||||
|
p.description === "" ? p.color : p.description,
|
||||||
|
PartNumber: p.partNumber,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
return arr;
|
||||||
|
}, []),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
return mappedData;
|
||||||
|
},
|
||||||
|
|
||||||
|
PartsFromApi() {
|
||||||
|
return store.getters.pageData(fmgPageValues.VEHICLE_PARTS);
|
||||||
|
},
|
||||||
|
|
||||||
|
RefPrefix() {
|
||||||
|
return "partQuestion";
|
||||||
|
},
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
arePagePrerequisitesValid() {
|
||||||
|
// Check if isRepair is populated and if the pageData we need is here (Parts data)
|
||||||
|
if (
|
||||||
|
store.getters.damage.isRepair !== null &&
|
||||||
|
Object.keys(store.getters.pageData(fmgPageValues.VEHICLE_PARTS))
|
||||||
|
.length !== 0
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
backButtonAction() {
|
||||||
|
this.$router.navigate(this.navigationScenarios.CLICKED_BACK, this.$route);
|
||||||
|
},
|
||||||
|
forwardButtonAction() {
|
||||||
|
const selectedGlassPartNumbers = [];
|
||||||
|
const matchedParts = [];
|
||||||
|
|
||||||
|
// Compile all selected parts from the page.
|
||||||
|
for (let [key, value] of Object.entries(this.glassParts)) {
|
||||||
|
for (let [glassKey, glassValue] of Object.entries(value)) {
|
||||||
|
selectedGlassPartNumbers.push(glassValue[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Match them to the parts from the API.
|
||||||
|
for (let [key, value] of Object.entries(
|
||||||
|
this.PartsFromApi.partsOrQuestions
|
||||||
|
)) {
|
||||||
|
for (let [partKey, partValue] of Object.entries(value.parts)) {
|
||||||
|
const currentPart =
|
||||||
|
this.PartsFromApi.partsOrQuestions[key].parts[partKey];
|
||||||
|
const isMatched = selectedGlassPartNumbers.some(
|
||||||
|
(p) => p === currentPart.partNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isMatched) {
|
||||||
|
matchedParts.push(currentPart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no parts could be matched, throw an error.
|
||||||
|
if (matchedParts.length === 0) {
|
||||||
|
throw new Error("Could not match any parts to the selected parts");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save parts to the store.
|
||||||
|
store.commit(storeMutations.UPDATE_PARTS, matchedParts);
|
||||||
|
|
||||||
|
// Navigate to the next page.
|
||||||
|
this.$router.navigateAfterSave(
|
||||||
|
this.navigationScenarios.SELECTED_PARTS,
|
||||||
|
this.$route
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
@ -99,8 +99,8 @@ export default {
|
||||||
},
|
},
|
||||||
resetDependentState() {
|
resetDependentState() {
|
||||||
// Invokes
|
// Invokes
|
||||||
store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
|
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
|
store.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -163,8 +163,8 @@ describe("vehicle-year.vue", () => {
|
||||||
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_CAR_ID, null)
|
||||||
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_VEHICLE_CATEGORY, null)
|
||||||
|
|
||||||
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_AND_DEPS)
|
expect(store.dispatch).toBeCalledWith(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES)
|
||||||
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_AND_DEPS)
|
expect(store.dispatch).toBeCalledWith(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES)
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -95,8 +95,8 @@ export default {
|
||||||
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
|
store.commit(storeMutations.UPDATE_VEHICLE_CATEGORY, null);
|
||||||
|
|
||||||
// Invokes
|
// Invokes
|
||||||
store.dispatch(storeActions.RESET_DAMAGE_AND_DEPS);
|
store.dispatch(storeActions.RESET_DAMAGE_STATE_AND_DEPENDENCIES);
|
||||||
store.dispatch(storeActions.RESET_REGISTRATION_AND_DEPS);
|
store.dispatch(storeActions.RESET_REGISTRATION_STATE_AND_DEPENDENCIES);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {
|
components: {
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,9 @@ export default {
|
||||||
|
|
||||||
return store.dispatch(type, payload);
|
return store.dispatch(type, payload);
|
||||||
},
|
},
|
||||||
|
savePageDataToStore(page, data){
|
||||||
|
store.commit(storeMutations.UPDATE_PAGE_DATA, { page: page, data: data });
|
||||||
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
storeActions() {
|
storeActions() {
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,14 @@ describe("baseMixin.js", () => {
|
||||||
expect(store.dispatch).toBeCalledWith(type, payload);
|
expect(store.dispatch).toBeCalledWith(type, payload);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("savePageDataToStore, should call store commit", () => {
|
||||||
|
const mixIn = getMixInInstance({});
|
||||||
|
|
||||||
|
mixIn.methods.savePageDataToStore('vehicle-year', {});
|
||||||
|
|
||||||
|
expect(store.commit).toBeCalledWith(storeMutations.UPDATE_PAGE_DATA, { page: 'vehicle-year', data: {}});
|
||||||
|
});
|
||||||
|
|
||||||
test("computed: storeActions should be equal to import object", () => {
|
test("computed: storeActions should be equal to import object", () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const mixIn = getMixInInstance({});
|
const mixIn = getMixInInstance({});
|
||||||
|
|
@ -91,9 +99,11 @@ function getMixInInstance({ isDispatchSuccess = true }) {
|
||||||
// Attach mocks to mixin
|
// Attach mocks to mixin
|
||||||
const baseMixIn = baseMixin;
|
const baseMixIn = baseMixin;
|
||||||
baseMixIn.methods.$route = route;
|
baseMixIn.methods.$route = route;
|
||||||
store.dispatch = storeDispatch;
|
|
||||||
baseMixIn.methods.storeActions = storeActions;
|
baseMixIn.methods.storeActions = storeActions;
|
||||||
baseMixIn.methods.widgetNames = widgetNames;
|
baseMixIn.methods.widgetNames = widgetNames;
|
||||||
|
|
||||||
|
store.dispatch = storeDispatch;
|
||||||
|
store.commit = jest.fn();
|
||||||
|
|
||||||
return baseMixIn;
|
return baseMixIn;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
// Supporting files
|
// Supporting files
|
||||||
import { createWebHistory, createRouter } from "vue-router";
|
import { createWebHistory, createRouter } from "vue-router";
|
||||||
import { storeActions } from "@/constants/store-actions";
|
import { storeActions } from "@/constants/store-actions";
|
||||||
|
import baseMixin from "@/mixins/base-mixin";
|
||||||
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
import { lazyLoadComponent } from "@/router/dynamic-routing/component-loader.js";
|
||||||
import { routingTable } from "@/router/router-constants/routing-table.js";
|
import { routingTable } from "@/router/router-constants/routing-table.js";
|
||||||
import { globalEvents, globalEventTypes } from "@/constants/events";
|
import { globalEvents, globalEventTypes } from "@/constants/events";
|
||||||
|
|
@ -56,17 +57,20 @@ const routes = [
|
||||||
try {
|
try {
|
||||||
// If we already have our route, go to it.
|
// If we already have our route, go to it.
|
||||||
if (router.hasRoute(to.query.fmgPage)) {
|
if (router.hasRoute(to.query.fmgPage)) {
|
||||||
|
|
||||||
// Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function.
|
// Since our route is already in scope, we can grab the component from it and call the arePagePrerequisitesValid function.
|
||||||
const component = router
|
let component = router.getRoutes().filter((x) => x.name === to.query.fmgPage)[0].components;
|
||||||
.getRoutes()
|
|
||||||
.filter((x) => x.name === to.query.fmgPage)[0].components;
|
// If the component hasn't been loaded fully, load it before we check prerequisites.
|
||||||
|
if (component.default.methods === undefined) {
|
||||||
|
component = await component.default();
|
||||||
|
}
|
||||||
|
|
||||||
if (!arePagePrerequisitesValid(component)) {
|
if (!arePagePrerequisitesValid(component)) {
|
||||||
await GoToFunnelStartOn404(next);
|
await GoToFunnelStartOn404(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return next({ name: to.query.fmgPage, query: to.query, params: to.params });
|
||||||
return next({ name: to.query.fmgPage, query: to.query, params: to.params });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get route info for the given url. Names will have a 1:1 relationship with names in the Cms.
|
// Get route info for the given url. Names will have a 1:1 relationship with names in the Cms.
|
||||||
|
|
@ -81,10 +85,7 @@ const routes = [
|
||||||
|
|
||||||
// Call the next components arePagePrerequisitesValid method before load.
|
// Call the next components arePagePrerequisitesValid method before load.
|
||||||
// If it returns false, use the 404 logic.
|
// If it returns false, use the 404 logic.
|
||||||
const nextComponent = await router
|
const nextComponent = await router.getRoutes().filter((x) => x.name === routeData[0].name)[0].components.default();
|
||||||
.getRoutes()
|
|
||||||
.filter((x) => x.name === routeData[0].name)[0]
|
|
||||||
.components.default();
|
|
||||||
|
|
||||||
if (!arePagePrerequisitesValid(nextComponent)) {
|
if (!arePagePrerequisitesValid(nextComponent)) {
|
||||||
await GoToFunnelStartOn404(next);
|
await GoToFunnelStartOn404(next);
|
||||||
|
|
@ -114,18 +115,18 @@ const router = createRouter({
|
||||||
|
|
||||||
//---------------------------------------------------------- Router Functions ----------------------------------------------------------
|
//---------------------------------------------------------- Router Functions ----------------------------------------------------------
|
||||||
|
|
||||||
router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => {
|
router.navigate = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) => {
|
||||||
navigate(scenario, currentRoute, false, optionalQuery, optionalParams);
|
navigate(scenario, currentRoute, false, optionalQuery, optionalParams, optionalPageData);
|
||||||
}
|
}
|
||||||
|
|
||||||
router.navigateAfterSave = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}) => {
|
router.navigateAfterSave = (scenario, currentRoute, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) => {
|
||||||
navigate(scenario, currentRoute, true, optionalQuery, optionalParams);
|
navigate(scenario, currentRoute, true, optionalQuery, optionalParams, optionalPageData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PRIVATE FUNCTIONS
|
// PRIVATE FUNCTIONS
|
||||||
|
|
||||||
// Navigate to the next route, depending on the scenario.
|
// Navigate to the next route, depending on the scenario.
|
||||||
function navigate(scenario, currentRoute, invalidateOnSave, optionalQuery = {}, optionalParams = {}) {
|
function navigate(scenario, currentRoute, invalidateOnSave, optionalQuery = {}, optionalParams = {}, optionalPageData = {}) {
|
||||||
if (!scenario) {
|
if (!scenario) {
|
||||||
console.error("No scenario provided. Please review the routing table.");
|
console.error("No scenario provided. Please review the routing table.");
|
||||||
return;
|
return;
|
||||||
|
|
@ -144,6 +145,9 @@ function navigate(scenario, currentRoute, invalidateOnSave, optionalQuery = {},
|
||||||
resetDependentState(currentComponent);
|
resetDependentState(currentComponent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append page data to the store for the NEXT page, if any. It will be an empty object if none is provided.
|
||||||
|
baseMixin.methods.savePageDataToStore(matchingScenarioMap.destinationFmgPageValue, optionalPageData);
|
||||||
|
|
||||||
router.push({
|
router.push({
|
||||||
name: "root",
|
name: "root",
|
||||||
query: Object.assign(optionalQuery, {
|
query: Object.assign(optionalQuery, {
|
||||||
|
|
@ -232,4 +236,4 @@ function resetDependentState(component) {
|
||||||
return component.default.methods.resetDependentState();
|
return component.default.methods.resetDependentState();
|
||||||
}
|
}
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
|
|
@ -4,6 +4,9 @@ const fmgPageValues = {
|
||||||
VEHICLE_MODEL: "vehicle-model",
|
VEHICLE_MODEL: "vehicle-model",
|
||||||
VEHICLE_STYLE: "vehicle-style",
|
VEHICLE_STYLE: "vehicle-style",
|
||||||
VEHICLE_DAMAGE: "vehicle-damage",
|
VEHICLE_DAMAGE: "vehicle-damage",
|
||||||
|
VEHICLE_PARTS: "vehicle-parts",
|
||||||
|
PART_QUESTIONS: "part-questions",
|
||||||
|
REVEAL : "reveal",
|
||||||
};
|
};
|
||||||
|
|
||||||
export { fmgPageValues };
|
export { fmgPageValues };
|
||||||
|
|
@ -4,6 +4,10 @@ const navigationScenarios = {
|
||||||
SELECTED_MAKE: "SELECTED_MAKE",
|
SELECTED_MAKE: "SELECTED_MAKE",
|
||||||
SELECTED_STYLE: "SELECTED_STYLE",
|
SELECTED_STYLE: "SELECTED_STYLE",
|
||||||
CLICKED_BACK: "CLICKED_BACK",
|
CLICKED_BACK: "CLICKED_BACK",
|
||||||
|
SELECTED_PARTS: "SELECTED_PARTS",
|
||||||
|
SELECTED_DAMAGE_WITH_SINGLE_PART: "SELECTED_DAMAGE_WITH_SINGLE_PART",
|
||||||
|
SELECTED_DAMAGE_WITH_MULTIPLE_PARTS: "SELECTED_DAMAGE_WITH_MULTIPLE_PARTS",
|
||||||
|
SELECTED_DAMAGE_WITH_PART_QUESTIONS: "SELECTED_DAMAGE_WITH_PART_QUESTIONS"
|
||||||
};
|
};
|
||||||
|
|
||||||
export { navigationScenarios };
|
export { navigationScenarios };
|
||||||
|
|
|
||||||
3
src/router/router-constants/router-parameter-keys.js
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
const routerParameterKeys = { };
|
||||||
|
|
||||||
|
export { routerParameterKeys };
|
||||||
|
|
@ -57,6 +57,49 @@ const routingTable = [
|
||||||
scenario: navigationScenarios.CLICKED_BACK,
|
scenario: navigationScenarios.CLICKED_BACK,
|
||||||
destinationFmgPageValue: fmgPageValues.VEHICLE_STYLE,
|
destinationFmgPageValue: fmgPageValues.VEHICLE_STYLE,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_SINGLE_PART,
|
||||||
|
destinationFmgPageValue: fmgPageValues.REVEAL,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||||
|
maps: [
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_BACK,
|
||||||
|
destinationFmgPageValue: fmgPageValues.VEHICLE_STYLE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_MULTIPLE_PARTS,
|
||||||
|
destinationFmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fmgPageValue: fmgPageValues.VEHICLE_PARTS,
|
||||||
|
maps: [
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_BACK,
|
||||||
|
destinationFmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.SELECTED_PARTS,
|
||||||
|
destinationFmgPageValue: fmgPageValues.REVEAL,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fmgPageValue: fmgPageValues.VEHICLE_DAMAGE,
|
||||||
|
maps: [
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.CLICKED_BACK,
|
||||||
|
destinationFmgPageValue: fmgPageValues.VEHICLE_STYLE,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
scenario: navigationScenarios.SELECTED_DAMAGE_WITH_PART_QUESTIONS,
|
||||||
|
destinationFmgPageValue: fmgPageValues.PART_QUESTIONS,
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -25,9 +25,14 @@ export const state = {
|
||||||
numberOfChips: null,
|
numberOfChips: null,
|
||||||
glassToReplace: null,
|
glassToReplace: null,
|
||||||
},
|
},
|
||||||
|
lineItems:{
|
||||||
|
glassParts: {},
|
||||||
|
otherParts: {}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
applicationUser: {
|
applicationUser: {
|
||||||
eventBus: [],
|
eventBus: [],
|
||||||
|
pageData: {}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -61,6 +66,21 @@ export const mutations = {
|
||||||
updateVehicleImageColor(state, imageColor) {
|
updateVehicleImageColor(state, imageColor) {
|
||||||
state.order.vehicle.imageColor = imageColor;
|
state.order.vehicle.imageColor = imageColor;
|
||||||
},
|
},
|
||||||
|
updateIsRepair(state, isRepair){
|
||||||
|
state.order.damage.isRepair = isRepair;
|
||||||
|
},
|
||||||
|
updateNumberOfChips(state, numberOfChips){
|
||||||
|
state.order.damage.numberOfChips = numberOfChips;
|
||||||
|
},
|
||||||
|
updateGlassToReplace(state, glassToReplace){
|
||||||
|
state.order.damage.glassToReplace = glassToReplace;
|
||||||
|
},
|
||||||
|
updateParts(state, partsData){
|
||||||
|
state.order.lineItems.glassParts = partsData;
|
||||||
|
},
|
||||||
|
updatePageData(state, pageData){
|
||||||
|
state.applicationUser.pageData[pageData.page] = pageData.data;
|
||||||
|
},
|
||||||
|
|
||||||
// EVENT BUS MUTATIONS
|
// EVENT BUS MUTATIONS
|
||||||
addEventToBus(state, event) {
|
addEventToBus(state, event) {
|
||||||
|
|
@ -81,7 +101,7 @@ export const mutations = {
|
||||||
},
|
},
|
||||||
|
|
||||||
// DEPENDENCY MUTATIONS
|
// DEPENDENCY MUTATIONS
|
||||||
resetVehicleAndDependencies(state) {
|
resetVehicleState(state) {
|
||||||
state.order.vehicle.year = null;
|
state.order.vehicle.year = null;
|
||||||
state.order.vehicle.make = null;
|
state.order.vehicle.make = null;
|
||||||
state.order.vehicle.model = null;
|
state.order.vehicle.model = null;
|
||||||
|
|
@ -89,7 +109,7 @@ export const mutations = {
|
||||||
state.order.vehicle.carId = null;
|
state.order.vehicle.carId = null;
|
||||||
state.order.vehicle.category = null;
|
state.order.vehicle.category = null;
|
||||||
},
|
},
|
||||||
resetDamageAndDependencies(state) {
|
resetDamageState(state) {
|
||||||
state.order.damage.isRepair = null;
|
state.order.damage.isRepair = null;
|
||||||
state.order.damage.numberOfChips = null;
|
state.order.damage.numberOfChips = null;
|
||||||
state.order.damage.windshieldGlassToReplace = null;
|
state.order.damage.windshieldGlassToReplace = null;
|
||||||
|
|
@ -98,11 +118,12 @@ export const mutations = {
|
||||||
state.order.damage.rearGlassToReplace = null;
|
state.order.damage.rearGlassToReplace = null;
|
||||||
|
|
||||||
},
|
},
|
||||||
resetRegistrationAndDependencies(state) {
|
resetRegistrationState(state) {
|
||||||
|
|
||||||
},
|
},
|
||||||
resetPartsAndDependencies(state) {
|
resetPartsState(state) {
|
||||||
|
state.order.lineItems.glassParts = null;
|
||||||
|
state.order.lineItems.otherParts = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -118,6 +139,11 @@ export const getters = {
|
||||||
return matchedEvent !== undefined ? matchedEvent.eventValue : undefined;
|
return matchedEvent !== undefined ? matchedEvent.eventValue : undefined;
|
||||||
},
|
},
|
||||||
eventBus: (state) => state.applicationUser.eventBus,
|
eventBus: (state) => state.applicationUser.eventBus,
|
||||||
|
damage: (state) => state.order.damage,
|
||||||
|
lineItems: (state) => state.order.lineItems,
|
||||||
|
pageData: (state) => (page) => {
|
||||||
|
return state.applicationUser.pageData[page];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Export Actions
|
// Export Actions
|
||||||
|
|
@ -193,20 +219,20 @@ export const actions = {
|
||||||
|
|
||||||
// DEPENDENCY ACTIONS
|
// DEPENDENCY ACTIONS
|
||||||
resetVehicleAndDependencies(context) {
|
resetVehicleAndDependencies(context) {
|
||||||
context.commit(storeMutations.RESET_VEHICLE_AND_DEPS);
|
context.commit(storeMutations.RESET_VEHICLE_STATE);
|
||||||
context.commit(storeMutations.RESET_DAMAGE_AND_DEPS);
|
context.commit(storeMutations.RESET_DAMAGE_STATE);
|
||||||
context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS);
|
context.commit(storeMutations.RESET_REGISTRATION_STATE);
|
||||||
},
|
},
|
||||||
resetDamageAndDependencies(context) {
|
resetDamageAndDependencies(context) {
|
||||||
context.commit(storeMutations.RESET_DAMAGE_AND_DEPS);
|
context.commit(storeMutations.RESET_DAMAGE_STATE);
|
||||||
context.commit(storeMutations.RESET_PARTS_AND_DEPS);
|
context.commit(storeMutations.RESET_PARTS_STATE);
|
||||||
},
|
},
|
||||||
resetRegistrationAndDependencies(context) {
|
resetRegistrationAndDependencies(context) {
|
||||||
context.commit(storeMutations.RESET_REGISTRATION_AND_DEPS);
|
context.commit(storeMutations.RESET_REGISTRATION_STATE);
|
||||||
context.commit(storeMutations.RESET_PARTS_AND_DEPS)
|
context.commit(storeMutations.RESET_PARTS_STATE)
|
||||||
},
|
},
|
||||||
resetPartsAndDependencies(context) {
|
resetPartsAndDependencies(context) {
|
||||||
context.commit(storeMutations.RESET_PARTS_AND_DEPS);
|
context.commit(storeMutations.RESET_PARTS_STATE);
|
||||||
},
|
},
|
||||||
|
|
||||||
// Content API Actions
|
// Content API Actions
|
||||||
|
|
@ -239,6 +265,20 @@ export const actions = {
|
||||||
payload: {},
|
payload: {},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Parts API Actions
|
||||||
|
getPartsOrQuestions(context, { carId, glassArray, zipCode, vin = '' }) {
|
||||||
|
return globalMethods.callHttpClient({
|
||||||
|
method: endpoints.GetPartsOrQuestions.method,
|
||||||
|
endpoint: endpoints.GetPartsOrQuestions.url,
|
||||||
|
payload: {
|
||||||
|
carId: carId,
|
||||||
|
glass: glassArray,
|
||||||
|
zip: zipCode,
|
||||||
|
vin: vin
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default createStore({
|
export default createStore({
|
||||||
|
|
@ -252,4 +292,4 @@ export default createStore({
|
||||||
mutations,
|
mutations,
|
||||||
getters,
|
getters,
|
||||||
actions,
|
actions,
|
||||||
});
|
});
|
||||||
|
|
@ -100,7 +100,7 @@ describe("Mutations", () => {
|
||||||
expect(storeState.applicationUser.eventBus).toEqual([{ EventOne: "ValueOne" }]);
|
expect(storeState.applicationUser.eventBus).toEqual([{ EventOne: "ValueOne" }]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("resetVehicleAndDependencies, should set fields to null", () => {
|
it("resetVehicleState, should set fields to null", () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const storeState = state;
|
const storeState = state;
|
||||||
|
|
||||||
|
|
@ -120,7 +120,7 @@ describe("Mutations", () => {
|
||||||
expect(storeState.order.vehicle.category).toEqual("CAR");
|
expect(storeState.order.vehicle.category).toEqual("CAR");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
mutations.resetVehicleAndDependencies(storeState);
|
mutations.resetVehicleState(storeState);
|
||||||
|
|
||||||
// Expect
|
// Expect
|
||||||
expect(storeState.order.vehicle.year).toEqual(null);
|
expect(storeState.order.vehicle.year).toEqual(null);
|
||||||
|
|
@ -132,7 +132,7 @@ describe("Mutations", () => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it("resetDamageAndDependencies, should set fields to null", () => {
|
it("resetDamageState, should set fields to null", () => {
|
||||||
// Arrange
|
// Arrange
|
||||||
const storeState = state;
|
const storeState = state;
|
||||||
|
|
||||||
|
|
@ -154,7 +154,7 @@ describe("Mutations", () => {
|
||||||
expect(storeState.order.damage.rearGlassToReplace).toEqual("Slider");
|
expect(storeState.order.damage.rearGlassToReplace).toEqual("Slider");
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
mutations.resetDamageAndDependencies(storeState);
|
mutations.resetDamageState(storeState);
|
||||||
|
|
||||||
// Expect
|
// Expect
|
||||||
expect(storeState.order.damage.isRepair).toEqual(null);
|
expect(storeState.order.damage.isRepair).toEqual(null);
|
||||||
|
|
@ -166,6 +166,50 @@ describe("Mutations", () => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Updates number of chips in state", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
mutations.updateNumberOfChips(storeState, "1");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(storeState.order.damage.numberOfChips).toEqual("1");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Updates glass to replace in state", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
mutations.updateGlassToReplace(storeState, ["Windshield"]);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(storeState.order.damage.glassToReplace).toEqual(["Windshield"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Updates Parts in state", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
mutations.updateParts(storeState, { 'Windshield-Single': 'PARTNUM101'});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(storeState.order.lineItems.glassParts).toEqual({ 'Windshield-Single': 'PARTNUM101'});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Updates page data in state", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
mutations.updatePageData(storeState, { page: 'vehicle-year', data: {} });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(storeState.applicationUser.pageData['vehicle-year']).toEqual({});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("Actions", () => {
|
describe("Actions", () => {
|
||||||
|
|
@ -313,9 +357,9 @@ describe("Actions", () => {
|
||||||
// Act
|
// Act
|
||||||
await actions.resetVehicleAndDependencies(context)
|
await actions.resetVehicleAndDependencies(context)
|
||||||
|
|
||||||
expect(commit).toBeCalledWith(storeMutations.RESET_VEHICLE_AND_DEPS);
|
expect(commit).toBeCalledWith(storeMutations.RESET_VEHICLE_STATE);
|
||||||
expect(commit).toBeCalledWith(storeMutations.RESET_DAMAGE_AND_DEPS);
|
expect(commit).toBeCalledWith(storeMutations.RESET_DAMAGE_STATE);
|
||||||
expect(commit).toBeCalledWith(storeMutations.RESET_REGISTRATION_AND_DEPS);
|
expect(commit).toBeCalledWith(storeMutations.RESET_REGISTRATION_STATE);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -330,8 +374,8 @@ describe("Actions", () => {
|
||||||
// Act
|
// Act
|
||||||
await actions.resetDamageAndDependencies(context)
|
await actions.resetDamageAndDependencies(context)
|
||||||
|
|
||||||
expect(commit).toBeCalledWith(storeMutations.RESET_DAMAGE_AND_DEPS);
|
expect(commit).toBeCalledWith(storeMutations.RESET_DAMAGE_STATE);
|
||||||
expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_AND_DEPS);
|
expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_STATE);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -346,8 +390,8 @@ describe("Actions", () => {
|
||||||
// Act
|
// Act
|
||||||
await actions.resetRegistrationAndDependencies(context)
|
await actions.resetRegistrationAndDependencies(context)
|
||||||
|
|
||||||
expect(commit).toBeCalledWith(storeMutations.RESET_REGISTRATION_AND_DEPS);
|
expect(commit).toBeCalledWith(storeMutations.RESET_REGISTRATION_STATE);
|
||||||
expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_AND_DEPS);
|
expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_STATE);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -362,7 +406,7 @@ describe("Actions", () => {
|
||||||
// Act
|
// Act
|
||||||
await actions.resetPartsAndDependencies(context)
|
await actions.resetPartsAndDependencies(context)
|
||||||
|
|
||||||
expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_AND_DEPS);
|
expect(commit).toBeCalledWith(storeMutations.RESET_PARTS_STATE);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -480,4 +524,41 @@ describe("Getters", () => {
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Damage getter, should return damage data", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
mutations.updateGlassToReplace(storeState, ["Rear"]);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(getters.damage(storeState).glassToReplace).toEqual(["Rear"]);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it("lineItems getter, should return lineItem data", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
mutations.updateParts(storeState, {"Rear-Stationary": 'PART101'});
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(getters.lineItems(storeState).glassParts).toEqual({"Rear-Stationary": 'PART101'});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it("PageData getter, should return page data for specific page", () => {
|
||||||
|
// Arrange
|
||||||
|
const storeState = state;
|
||||||
|
|
||||||
|
// Act
|
||||||
|
mutations.updatePageData(storeState, { page: 'vehicle-year', data: {} });
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
expect(getters.pageData(storeState)('vehicle-year')).toEqual({});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
.fade-enter-active{
|
.fade-enter-active {
|
||||||
transition: opacity 0.6s ease;
|
transition: opacity 0.8s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fade-leave-active {
|
.fade-leave-active {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
body {
|
body {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
max-width: 576px; //Remove once desktop app is complete
|
max-width: 576px; //Remove once desktop app is complete
|
||||||
&.container-shadow {
|
&.container-shadow {
|
||||||
|
|
@ -14,6 +13,9 @@ body {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.prevent-squish{
|
||||||
|
overflow-x: unset;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.pointer {
|
.pointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
|
||||||
|
|
@ -204,11 +204,12 @@ describe("list-card.vue", () => {
|
||||||
isRequired: true,
|
isRequired: true,
|
||||||
isWide: false,
|
isWide: false,
|
||||||
modelValue: ["List Card Checkbox"],
|
modelValue: ["List Card Checkbox"],
|
||||||
|
buttonID: 'list-card-id'
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
wrapper.vm.handleCheckChange();
|
wrapper.vm.handleCheckChange();
|
||||||
// Assert
|
// Assert
|
||||||
expect(wrapper.emitted()["isCheckedChanged"][0]).toEqual([{value: "List Card Checkbox", checkValue: [Boolean, String]}]);
|
expect(wrapper.emitted()["isCheckedChanged"][0]).toEqual([{value: "List Card Checkbox", checkValue: [Boolean, String], buttonId: 'list-card-id'}]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Should set checkValue data if selectedButtonIDs has value(s)", async () => {
|
it("Should set checkValue data if selectedButtonIDs has value(s)", async () => {
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,6 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { useField } from "vee-validate";
|
import { useField } from "vee-validate";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "listCard",
|
name: "listCard",
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -102,7 +101,9 @@ export default {
|
||||||
handleCheckChange(newValue, oldValue){
|
handleCheckChange(newValue, oldValue){
|
||||||
const isInitialization = typeof(oldValue) === 'function';
|
const isInitialization = typeof(oldValue) === 'function';
|
||||||
if (!isInitialization) {
|
if (!isInitialization) {
|
||||||
this.$emit('isCheckedChanged', { checkValue: this.checkValue, value: this.value.toString() });
|
const emitEvent = { checkValue: this.checkValue, value: this.value.toString(), buttonId: this.buttonID.toString() };
|
||||||
|
this.$emit('isCheckedChanged', emitEvent);
|
||||||
|
this.$emit('update:modelValue', emitEvent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -284,4 +285,4 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -60,4 +60,42 @@ describe("radio.vue", () => {
|
||||||
|
|
||||||
expect(paragraph.text()).toEqual("screenreader text");
|
expect(paragraph.text()).toEqual("screenreader text");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Should emit button value on click", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(radio, {
|
||||||
|
propsData: {
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
value: "List Card Checkbox",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
isRequired: true,
|
||||||
|
isWide: false,
|
||||||
|
modelValue: ["List Card Checkbox"],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
wrapper.vm.handleCheckChange();
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.emitted()["isCheckedChanged"][0]).toEqual([{"buttonID": "List Card Checkbox", value: "List Card Checkbox", checkValue: false}]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Should set checkValue data if selectedButtonIDs has value(s)", async () => {
|
||||||
|
// Act
|
||||||
|
const wrapper = shallowMount(radio, {
|
||||||
|
propsData: {
|
||||||
|
buttonLabel: "Windshield",
|
||||||
|
buttonID: "List Card Checkbox",
|
||||||
|
groupID: "radio-demo-1",
|
||||||
|
groupName: "radio 1",
|
||||||
|
buttonImage: "windshield-damage.svg",
|
||||||
|
isRequired: true,
|
||||||
|
modelValue: ["List Card Checkbox"],
|
||||||
|
value: "Car-Front",
|
||||||
|
selectedValues: ["Car-Front"]
|
||||||
|
},
|
||||||
|
});
|
||||||
|
// Assert
|
||||||
|
expect(wrapper.componentVM.checkValue).toEqual(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
:value="value"
|
:value="value"
|
||||||
:v-model="checkValue"
|
:v-model="checkValue"
|
||||||
@change="handleCheckChange()"
|
@change="handleCheckChange()"
|
||||||
|
:checked="checkValue"
|
||||||
/>
|
/>
|
||||||
<label class="d-flex align-items-start form-check-label" :for="buttonID">
|
<label class="d-flex align-items-start form-check-label" :for="buttonID">
|
||||||
<p v-if="buttonLabel" class="m-0">{{ buttonLabel }}</p>
|
<p v-if="buttonLabel" class="m-0">{{ buttonLabel }}</p>
|
||||||
|
|
@ -36,6 +37,7 @@ export default {
|
||||||
default: "",
|
default: "",
|
||||||
},
|
},
|
||||||
screenReaderOnlyText: String,
|
screenReaderOnlyText: String,
|
||||||
|
selectedValues: [Array, String],
|
||||||
hasError: Boolean,
|
hasError: Boolean,
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -43,36 +45,46 @@ export default {
|
||||||
checkValue: Boolean,
|
checkValue: Boolean,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created(){
|
created() {
|
||||||
if(this.selectedButtonIDs){
|
if (this.selectedValues) {
|
||||||
this.checkValue = this.selectedButtonIDs[0];
|
this.checkValue = this.selectedValues[0] === this.value;
|
||||||
|
}else{
|
||||||
|
this.checkValue = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleClick(value) {
|
handleClick(value) {
|
||||||
this.handleChange(value);
|
this.handleChange(value);
|
||||||
},
|
},
|
||||||
handleCheckChange(newValue, oldValue){
|
handleCheckChange(newValue, oldValue) {
|
||||||
const isInitialization = typeof(oldValue) === 'function';
|
const isInitialization = typeof oldValue === "function";
|
||||||
if (!isInitialization) {
|
if (!isInitialization) {
|
||||||
this.$emit('isCheckedChanged', { checkValue: this.checkValue, value: this.value.toString() });
|
|
||||||
|
const emitEvent = {
|
||||||
|
checkValue: this.checkValue,
|
||||||
|
value: this.value.toString(),
|
||||||
|
buttonID: this.buttonID.toString(),
|
||||||
|
};
|
||||||
|
|
||||||
|
this.$emit("isCheckedChanged", emitEvent);
|
||||||
|
this.$emit("update:modelValue", emitEvent);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
setup(props) {
|
setup(props) {
|
||||||
const { groupName, value } = toRefs(props);
|
const inputType = "radio";
|
||||||
const { checked, handleChange, errorMessage } = useField(
|
const {
|
||||||
groupName,
|
value: inputValue,
|
||||||
undefined,
|
handleChange,
|
||||||
{
|
errors,
|
||||||
type: "radio",
|
} = useField(props.groupName, props.validationRules,
|
||||||
checkedValue: value,
|
{
|
||||||
}
|
type: inputType,
|
||||||
);
|
checkedValue: props.value,
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
checked,
|
|
||||||
handleChange,
|
handleChange,
|
||||||
errorMessage,
|
errors,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
@ -83,7 +95,7 @@ export default {
|
||||||
.form-check-input {
|
.form-check-input {
|
||||||
border: 1px solid $gray-500;
|
border: 1px solid $gray-500;
|
||||||
border-radius: 100%;
|
border-radius: 100%;
|
||||||
margin-right: .5rem;
|
margin-right: 0.5rem;
|
||||||
&:checked {
|
&:checked {
|
||||||
background-color: $white;
|
background-color: $white;
|
||||||
background-size: 71%;
|
background-size: 71%;
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ export default {
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
a {
|
a {
|
||||||
|
display: inline-flex !important;
|
||||||
color: $blue;
|
color: $blue;
|
||||||
text-underline-offset: 0.5em;
|
text-underline-offset: 0.5em;
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
|
|
@ -42,7 +43,6 @@ a {
|
||||||
&.navigation-link {
|
&.navigation-link {
|
||||||
color: $black;
|
color: $black;
|
||||||
line-height: 26px;
|
line-height: 26px;
|
||||||
display: inline-flex;
|
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
|
||||||