Merge branch 'develop' into feature/kiener/INSR-7753
This commit is contained in:
commit
d0b970e68a
61 changed files with 2359 additions and 1615 deletions
199
package-lock.json
generated
199
package-lock.json
generated
|
|
@ -142,7 +142,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.19.0.tgz",
|
||||
"integrity": "sha512-reM4+U7B9ss148rh2n1Qs9ASS+w94irYXga7c2jaQv9RVzpS7Mv1a9rnYYwuDa45G+DkORt9g6An2k/V4d9LbQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.1.0",
|
||||
"@babel/code-frame": "^7.18.6",
|
||||
|
|
@ -2374,7 +2373,8 @@
|
|||
"integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/@hapi/hoek": {
|
||||
"version": "9.3.0",
|
||||
|
|
@ -3281,6 +3281,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@gar/promisify": "^1.0.1",
|
||||
"semver": "^7.3.5"
|
||||
|
|
@ -3293,6 +3294,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
|
|
@ -3308,6 +3310,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"mkdirp": "^1.0.4",
|
||||
"rimraf": "^3.0.2"
|
||||
|
|
@ -3323,6 +3326,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
|
|
@ -3393,7 +3397,6 @@
|
|||
"integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"playwright": "1.56.1"
|
||||
},
|
||||
|
|
@ -3973,7 +3976,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.19.1.tgz",
|
||||
"integrity": "sha512-P6iIPyYQ+qH8CvGauAqanhVnjrnRe0IZFSYCeGkSRW9q3u8bdVn2NPI+lasFyVsEQn1J/IFmp5Aax41+dAP9wg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
|
|
@ -4440,7 +4442,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-12.2.3.tgz",
|
||||
"integrity": "sha512-GKMHFfv3458yYy+v/N8gjufHO6MSZKCOXpZc5GXIWWy8uldwfmPn98vp81gZ5f9SVw8YYBctgfJ22a2d7AOMeQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/linkify-it": "*",
|
||||
"@types/mdurl": "*"
|
||||
|
|
@ -4625,7 +4626,6 @@
|
|||
"integrity": "sha512-h2lUByouOXFAlMec2mILeELUbME5SZRN/7R9Cw2RD2lRQQY08MWMM+PmVVKKJNK1aIwqTo9t/0CvOxwPbRIE2Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@typescript-eslint/scope-manager": "8.23.0",
|
||||
"@typescript-eslint/types": "8.23.0",
|
||||
|
|
@ -5419,7 +5419,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-5.0.8.tgz",
|
||||
"integrity": "sha512-nV7tYQLe7YsTtzFrfOMIHc5N2hp5lHG2rpYr0aNja9rNljdgcPZLyQRb2YRivTHqTv7lI962UXFURcpStHgyFw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/helper-compilation-targets": "^7.12.16",
|
||||
"@soda/friendly-errors-webpack-plugin": "^1.8.0",
|
||||
|
|
@ -5640,7 +5639,6 @@
|
|||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.4.tgz",
|
||||
"integrity": "sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/parser": "^7.20.15",
|
||||
"@vue/compiler-core": "3.3.4",
|
||||
|
|
@ -5775,7 +5773,6 @@
|
|||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.4.tgz",
|
||||
"integrity": "sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-ssr": "3.3.4",
|
||||
"@vue/shared": "3.3.4"
|
||||
|
|
@ -5848,7 +5845,6 @@
|
|||
"resolved": "https://registry.npmjs.org/@vue/vue3-jest/-/vue3-jest-27.0.0.tgz",
|
||||
"integrity": "sha512-VL61CgZBoQqayXfzlZJHHpZuX4lsT8dmdZMJzADhdAJjKu26JBpypHr/2ppevxItljPiuALQW4MKhhCXZRXnLg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/plugin-transform-modules-commonjs": "^7.2.0",
|
||||
"chalk": "^2.1.0",
|
||||
|
|
@ -6097,7 +6093,6 @@
|
|||
"resolved": "https://registry.npmjs.org/acorn/-/acorn-8.9.0.tgz",
|
||||
"integrity": "sha512-jaVNAFBHNLXspO543WnNNPZFRtavh3skAkITqD0/2aeMkKZTN+254PyhwxFYrk3vQ1xfY+2wbesJMs/JC8/PwQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"acorn": "bin/acorn"
|
||||
},
|
||||
|
|
@ -6201,6 +6196,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"humanize-ms": "^1.2.1"
|
||||
},
|
||||
|
|
@ -6215,6 +6211,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"clean-stack": "^2.0.0",
|
||||
"indent-string": "^4.0.0"
|
||||
|
|
@ -6228,7 +6225,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
|
||||
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"fast-json-stable-stringify": "^2.0.0",
|
||||
|
|
@ -6361,7 +6357,8 @@
|
|||
"integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/arch": {
|
||||
"version": "2.2.0",
|
||||
|
|
@ -6400,6 +6397,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"delegates": "^1.0.0",
|
||||
"readable-stream": "^3.6.0"
|
||||
|
|
@ -6599,7 +6597,6 @@
|
|||
"integrity": "sha512-oXTDccv8PcfjZmPGlWsPSwtOJCZ/b6W5jAMCNcfwJbCzDckwG0jrYJFaWH1yvivfCXjVzV/SPDEhMB3Q+DSurg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"follow-redirects": "^1.15.6",
|
||||
"form-data": "^4.0.4",
|
||||
|
|
@ -6663,7 +6660,6 @@
|
|||
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-27.5.1.tgz",
|
||||
"integrity": "sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/transform": "^27.5.1",
|
||||
"@jest/types": "^27.5.1",
|
||||
|
|
@ -6984,6 +6980,7 @@
|
|||
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"file-uri-to-path": "1.0.0"
|
||||
}
|
||||
|
|
@ -7128,7 +7125,6 @@
|
|||
"url": "https://github.com/sponsors/ai"
|
||||
}
|
||||
],
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001646",
|
||||
"electron-to-chromium": "^1.5.4",
|
||||
|
|
@ -7217,6 +7213,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@npmcli/fs": "^1.0.0",
|
||||
"@npmcli/move-file": "^1.0.1",
|
||||
|
|
@ -7248,6 +7245,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
|
|
@ -7490,6 +7488,7 @@
|
|||
"integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
|
|
@ -7534,6 +7533,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
@ -7748,6 +7748,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"color-support": "bin.js"
|
||||
}
|
||||
|
|
@ -8090,7 +8091,8 @@
|
|||
"integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/consolidate": {
|
||||
"version": "0.15.1",
|
||||
|
|
@ -8292,7 +8294,6 @@
|
|||
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.7.1.tgz",
|
||||
"integrity": "sha512-yB5CNFa14MbPJcomwNh3wLThtkZgcNyI2bNMRt8iE5Z8Vwl7f8vQXFAzn2HDOJvtDq2NTZBUGMSUNNyrv3/+cw==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"icss-utils": "^5.1.0",
|
||||
"postcss": "^8.4.7",
|
||||
|
|
@ -8369,7 +8370,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
|
||||
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
|
|
@ -8642,6 +8642,7 @@
|
|||
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"mimic-response": "^3.1.0"
|
||||
},
|
||||
|
|
@ -8706,6 +8707,7 @@
|
|||
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=4.0.0"
|
||||
}
|
||||
|
|
@ -8922,7 +8924,8 @@
|
|||
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "2.0.0",
|
||||
|
|
@ -8949,6 +8952,7 @@
|
|||
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -8969,10 +8973,11 @@
|
|||
"dev": true
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
|
||||
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
|
||||
"version": "4.0.4",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
|
||||
"integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
|
|
@ -9125,7 +9130,6 @@
|
|||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
|
||||
"integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
|
|
@ -9297,6 +9301,33 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/encoding": {
|
||||
"version": "0.1.13",
|
||||
"resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
|
||||
"integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"iconv-lite": "^0.6.2"
|
||||
}
|
||||
},
|
||||
"node_modules/encoding/node_modules/iconv-lite": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
|
||||
"integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
|
|
@ -9335,6 +9366,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
@ -9345,7 +9377,8 @@
|
|||
"integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/error-ex": {
|
||||
"version": "1.3.2",
|
||||
|
|
@ -9604,7 +9637,6 @@
|
|||
"deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@eslint-community/eslint-utils": "^4.2.0",
|
||||
"@eslint-community/regexpp": "^4.6.1",
|
||||
|
|
@ -9736,7 +9768,6 @@
|
|||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.26.0.tgz",
|
||||
"integrity": "sha512-hYfi3FXaM8WPLf4S1cikh/r4IxnO6zrhZbEGz2b660EJRbuxgpDS5gkCuYgGWg2xxh2rBuIr4Pvhve/7c31koA==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"array-includes": "^3.1.4",
|
||||
"array.prototype.flat": "^1.2.5",
|
||||
|
|
@ -10363,6 +10394,7 @@
|
|||
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
|
||||
"dev": true,
|
||||
"license": "(MIT OR WTFPL)",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
|
|
@ -10621,7 +10653,8 @@
|
|||
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
|
||||
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/fill-range": {
|
||||
"version": "7.1.1",
|
||||
|
|
@ -10886,7 +10919,8 @@
|
|||
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "9.1.0",
|
||||
|
|
@ -10909,6 +10943,7 @@
|
|||
"integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
|
|
@ -10986,6 +11021,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"aproba": "^1.0.3 || ^2.0.0",
|
||||
"color-support": "^1.1.3",
|
||||
|
|
@ -11099,7 +11135,8 @@
|
|||
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
|
||||
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "7.2.3",
|
||||
|
|
@ -11291,7 +11328,8 @@
|
|||
"integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/hash-sum": {
|
||||
"version": "2.0.0",
|
||||
|
|
@ -11476,7 +11514,8 @@
|
|||
"integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==",
|
||||
"dev": true,
|
||||
"license": "BSD-2-Clause",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/http-deceiver": {
|
||||
"version": "1.2.7",
|
||||
|
|
@ -11587,6 +11626,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ms": "^2.0.0"
|
||||
}
|
||||
|
|
@ -11731,7 +11771,8 @@
|
|||
"integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/inflight": {
|
||||
"version": "1.0.6",
|
||||
|
|
@ -11776,6 +11817,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"jsbn": "1.1.0",
|
||||
"sprintf-js": "^1.1.3"
|
||||
|
|
@ -11790,7 +11832,8 @@
|
|||
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
||||
"dev": true,
|
||||
"license": "BSD-3-Clause",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/ipaddr.js": {
|
||||
"version": "2.0.1",
|
||||
|
|
@ -12044,7 +12087,8 @@
|
|||
"integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/is-map": {
|
||||
"version": "2.0.2",
|
||||
|
|
@ -12473,7 +12517,6 @@
|
|||
"resolved": "https://registry.npmjs.org/jest/-/jest-27.5.1.tgz",
|
||||
"integrity": "sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@jest/core": "^27.5.1",
|
||||
"import-local": "^3.0.2",
|
||||
|
|
@ -15187,7 +15230,8 @@
|
|||
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/jsdoc": {
|
||||
"version": "4.0.2",
|
||||
|
|
@ -15513,10 +15557,11 @@
|
|||
}
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
"version": "4.17.23",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.debounce": {
|
||||
"version": "4.0.8",
|
||||
|
|
@ -15860,6 +15905,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"agentkeepalive": "^4.1.3",
|
||||
"cacache": "^15.2.0",
|
||||
|
|
@ -15889,6 +15935,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 6"
|
||||
}
|
||||
|
|
@ -15900,6 +15947,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@tootallnate/once": "1",
|
||||
"agent-base": "6",
|
||||
|
|
@ -16122,6 +16170,7 @@
|
|||
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
|
|
@ -16162,7 +16211,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
|
||||
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
|
|
@ -16258,6 +16306,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
|
|
@ -16272,6 +16321,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.1.0",
|
||||
"minipass-sized": "^1.0.3",
|
||||
|
|
@ -16291,6 +16341,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
|
|
@ -16305,6 +16356,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
|
|
@ -16319,6 +16371,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0"
|
||||
},
|
||||
|
|
@ -16332,6 +16385,7 @@
|
|||
"integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"minipass": "^3.0.0",
|
||||
"yallist": "^4.0.0"
|
||||
|
|
@ -16357,7 +16411,8 @@
|
|||
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
|
||||
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/module-alias": {
|
||||
"version": "2.2.2",
|
||||
|
|
@ -16428,7 +16483,8 @@
|
|||
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/natural-compare": {
|
||||
"version": "1.4.0",
|
||||
|
|
@ -16473,6 +16529,7 @@
|
|||
"integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"semver": "^7.3.5"
|
||||
},
|
||||
|
|
@ -16486,6 +16543,7 @@
|
|||
"integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
|
|
@ -16498,7 +16556,8 @@
|
|||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
|
||||
"integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/node-fetch": {
|
||||
"version": "2.6.7",
|
||||
|
|
@ -16559,6 +16618,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"env-paths": "^2.2.0",
|
||||
"glob": "^7.1.4",
|
||||
|
|
@ -16585,6 +16645,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"abbrev": "1"
|
||||
},
|
||||
|
|
@ -16602,6 +16663,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"semver": "bin/semver.js"
|
||||
},
|
||||
|
|
@ -16616,6 +16678,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"isexe": "^2.0.0"
|
||||
},
|
||||
|
|
@ -16724,6 +16787,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"are-we-there-yet": "^3.0.0",
|
||||
"console-control-strings": "^1.1.0",
|
||||
|
|
@ -17077,6 +17141,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"aggregate-error": "^3.0.0"
|
||||
},
|
||||
|
|
@ -17313,7 +17378,6 @@
|
|||
"version": "2.1.4",
|
||||
"resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.4.tgz",
|
||||
"integrity": "sha512-vYlnDu+Y/FXxv1ABo1vhjC+IbqvzUdiUC3sfDRrRyY2CQSrqqaa+iiHmqtARFxJVqWQMCJfXx1PBvFs9aJVLXQ==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.5.0",
|
||||
"vue-demi": ">=0.14.5"
|
||||
|
|
@ -17468,7 +17532,6 @@
|
|||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"nanoid": "^3.3.11",
|
||||
"picocolors": "^1.1.1",
|
||||
|
|
@ -18001,6 +18064,7 @@
|
|||
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"detect-libc": "^2.0.0",
|
||||
"expand-template": "^2.0.3",
|
||||
|
|
@ -18116,7 +18180,8 @@
|
|||
"integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/promise-retry": {
|
||||
"version": "2.0.1",
|
||||
|
|
@ -18125,6 +18190,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"err-code": "^2.0.2",
|
||||
"retry": "^0.12.0"
|
||||
|
|
@ -18140,6 +18206,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 4"
|
||||
}
|
||||
|
|
@ -18319,6 +18386,7 @@
|
|||
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
|
||||
"dev": true,
|
||||
"license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
|
|
@ -18335,6 +18403,7 @@
|
|||
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
|
|
@ -18783,7 +18852,6 @@
|
|||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.77.8.tgz",
|
||||
"integrity": "sha512-4UHg6prsrycW20fqLGPShtEvo/WyHRVRHwOP4DzkUrObWoWI05QBSfzU71TVB7PFaL104TwNaHpjlWXAZbQiNQ==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chokidar": ">=3.0.0 <4.0.0",
|
||||
"immutable": "^4.0.0",
|
||||
|
|
@ -19064,7 +19132,8 @@
|
|||
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true
|
||||
"optional": true,
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/set-function-length": {
|
||||
"version": "1.2.2",
|
||||
|
|
@ -19252,7 +19321,8 @@
|
|||
"url": "https://feross.org/support"
|
||||
}
|
||||
],
|
||||
"license": "MIT"
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/simple-get": {
|
||||
"version": "4.0.1",
|
||||
|
|
@ -19274,6 +19344,7 @@
|
|||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"decompress-response": "^6.0.0",
|
||||
"once": "^1.3.1",
|
||||
|
|
@ -19316,6 +19387,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 6.0.0",
|
||||
"npm": ">= 3.0.0"
|
||||
|
|
@ -19348,6 +19420,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"ip-address": "^9.0.5",
|
||||
"smart-buffer": "^4.2.0"
|
||||
|
|
@ -19364,6 +19437,7 @@
|
|||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"agent-base": "^6.0.2",
|
||||
"debug": "^4.3.3",
|
||||
|
|
@ -19912,6 +19986,7 @@
|
|||
"integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chownr": "^2.0.0",
|
||||
"fs-minipass": "^2.0.0",
|
||||
|
|
@ -19930,6 +20005,7 @@
|
|||
"integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"chownr": "^1.1.1",
|
||||
"mkdirp-classic": "^0.5.2",
|
||||
|
|
@ -19942,7 +20018,8 @@
|
|||
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
|
||||
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
"license": "ISC",
|
||||
"peer": true
|
||||
},
|
||||
"node_modules/tar-fs/node_modules/tar-stream": {
|
||||
"version": "2.2.0",
|
||||
|
|
@ -19950,6 +20027,7 @@
|
|||
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"bl": "^4.0.3",
|
||||
"end-of-stream": "^1.4.1",
|
||||
|
|
@ -19979,6 +20057,7 @@
|
|||
"integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
|
|
@ -19989,6 +20068,7 @@
|
|||
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"mkdirp": "bin/cmd.js"
|
||||
},
|
||||
|
|
@ -20225,7 +20305,6 @@
|
|||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
|
|
@ -20503,6 +20582,7 @@
|
|||
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"safe-buffer": "^5.0.1"
|
||||
},
|
||||
|
|
@ -20558,7 +20638,6 @@
|
|||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||
"devOptional": true,
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
|
|
@ -20698,6 +20777,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"unique-slug": "^2.0.0"
|
||||
}
|
||||
|
|
@ -20709,6 +20789,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"imurmurhash": "^0.1.4"
|
||||
}
|
||||
|
|
@ -20872,7 +20953,6 @@
|
|||
"integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.4.4",
|
||||
|
|
@ -21004,7 +21084,6 @@
|
|||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
|
|
@ -21018,7 +21097,6 @@
|
|||
"integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/chai": "^5.2.2",
|
||||
"@vitest/expect": "3.2.4",
|
||||
|
|
@ -21171,7 +21249,6 @@
|
|||
"version": "3.3.4",
|
||||
"resolved": "https://registry.npmjs.org/vue/-/vue-3.3.4.tgz",
|
||||
"integrity": "sha512-VTyEYn3yvIeY1Py0WaYGZsXnz3y5UnGi62GjVEqvEGPl6nxbOrCXbVOTQWBEJUqAyTUk2uJ5JLVnYJ6ZzGbrSw==",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vue/compiler-dom": "3.3.4",
|
||||
"@vue/compiler-sfc": "3.3.4",
|
||||
|
|
@ -21482,7 +21559,6 @@
|
|||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz",
|
||||
"integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "^1.0.5",
|
||||
"@webassemblyjs/ast": "^1.12.1",
|
||||
|
|
@ -21698,7 +21774,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
|
||||
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
|
|
@ -21807,7 +21882,6 @@
|
|||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.11.0.tgz",
|
||||
"integrity": "sha512-wGgprdCvMalC0BztXvitD2hC04YffAvtsUn93JbGXYLAtCUO4xd17mCCZQxUOItiBwZvJScWo8NIvQMQ71rdpg==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"fast-deep-equal": "^3.1.1",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
|
|
@ -21874,7 +21948,6 @@
|
|||
"resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
|
||||
"integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
|
||||
"dev": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
}
|
||||
|
|
@ -22047,6 +22120,7 @@
|
|||
"dev": true,
|
||||
"license": "ISC",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"string-width": "^1.0.2 || 2 || 3 || 4"
|
||||
}
|
||||
|
|
@ -22182,7 +22256,6 @@
|
|||
"integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
|
|
|
|||
3
src/assets/img/icons/alert-circle.svg
Normal file
3
src/assets/img/icons/alert-circle.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="21" viewBox="0 0 20 21">
|
||||
<path fill="#E86421" fill-rule="nonzero" d="M10 .5c5.523 0 10 4.477 10 10s-4.477 10-10 10-10-4.477-10-10S4.477.5 10 .5zm.043 13.6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm.77-9.2h-1.54l-.088.009a.502.502 0 0 0-.299.193.66.66 0 0 0-.125.47l.747 6.806.017.096c.065.249.263.425.495.426l.084-.008c.22-.042.396-.246.427-.51l.793-6.805.004-.102a.651.651 0 0 0-.127-.37.489.489 0 0 0-.388-.205z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 474 B |
3
src/assets/img/icons/chevron-up.svg
Normal file
3
src/assets/img/icons/chevron-up.svg
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="9" viewBox="0 0 15 9">
|
||||
<path fill="#E86421" fill-rule="nonzero" d="M7.5 0a.806.806 0 0 0-.593.265L.246 7.455a.957.957 0 0 0 0 1.28.796.796 0 0 0 1.185 0l6.07-6.55 6.068 6.55a.796.796 0 0 0 1.186 0 .957.957 0 0 0 0-1.28L8.093.265A.806.806 0 0 0 7.5 0"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 323 B |
|
|
@ -1,9 +0,0 @@
|
|||
const buttonVariants = Object.freeze({
|
||||
primary: 'primary',
|
||||
secondary: 'secondary',
|
||||
success: 'success',
|
||||
link: 'link',
|
||||
navigation: 'navigation'
|
||||
});
|
||||
|
||||
export default buttonVariants;
|
||||
15
src/constants/component-variants.js
Normal file
15
src/constants/component-variants.js
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
export const buttonVariants = Object.freeze({
|
||||
primary: 'primary',
|
||||
secondary: 'secondary',
|
||||
success: 'success',
|
||||
link: 'link',
|
||||
navigation: 'navigation'
|
||||
});
|
||||
export const dropdownVariants = Object.freeze({
|
||||
primary: 'primary',
|
||||
compact: 'compact'
|
||||
});
|
||||
export const modalPositions = Object.freeze({
|
||||
center: 'center',
|
||||
edge: 'edge'
|
||||
});
|
||||
|
|
@ -23,8 +23,13 @@ const errorMessages = Object.freeze({
|
|||
LAST_NAME_REQUIRED: 'Please enter your last name',
|
||||
EMAIL_ADDRESS_REQUIRED: 'Email is required.',
|
||||
EMAIL_ADDRESS_FORMAT: 'Please enter a valid email address.',
|
||||
SERVICE_ZIP_REQUIRED: 'Please enter your service ZIP',
|
||||
SERVICE_ZIP_FORMAT: 'Please enter a valid service ZIP',
|
||||
SERVICE_ZIP_REQUIRED: 'ZIP code is required',
|
||||
SERVICE_ZIP_FORMAT: 'Invalid ZIP, please enter a new ZIP (5 characters)',
|
||||
MOBILE_SERVICE_ZIP_FORMAT: 'Invalid ZIP code',
|
||||
NO_SERVICE_IN_AREA: (area) => `We're sorry, but we don't offer service in ${area} at this time.`,
|
||||
PROVIDER_REQUIRED: 'Please select a provider.',
|
||||
INVALID_ZIP: 'The ZIP you entered was invalid. Please enter a valid ZIP.',
|
||||
ZIP_CODE_NOT_SERVICED_FOR_VEHICLE: 'We do not currently offer glass service for your vehicle in this ZIP code. Please try another ZIP code.',
|
||||
VIN_REQUIRED: 'Please enter your VIN',
|
||||
VIN_FORMAT:
|
||||
// eslint-disable-next-line max-len
|
||||
|
|
|
|||
|
|
@ -71,6 +71,9 @@ export const pageProgressMapper = {
|
|||
'tpa-search': {
|
||||
percent: 85
|
||||
},
|
||||
'tpa-submit': {
|
||||
percent: 95
|
||||
},
|
||||
'tpa-confirmation': {
|
||||
percent: 100
|
||||
},
|
||||
|
|
|
|||
|
|
@ -294,6 +294,11 @@ export default {
|
|||
this.resetField({
|
||||
value: newValue
|
||||
});
|
||||
},
|
||||
answers() {
|
||||
this.resetField({
|
||||
value: this.modelValue
|
||||
});
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@
|
|||
<div
|
||||
class="dropdown-question"
|
||||
:class="{
|
||||
'has-error' : (meta.touched && errors && errors.length && !isDisabled) || hasError,
|
||||
'has-success': (meta.touched && (!errors || !errors.length) && !isDisabled)
|
||||
'has-error' : (meta?.touched && errors && errors.length && !isDisabled) || hasError,
|
||||
'has-success': (meta?.touched && (!errors || !errors.length) && !isDisabled),
|
||||
[`dropdown-${variant}`]: true
|
||||
}">
|
||||
<label
|
||||
:for="inputId"
|
||||
|
|
@ -34,7 +35,7 @@
|
|||
</option>
|
||||
</select>
|
||||
<div
|
||||
v-show="meta.touched && errorMessage && !isDisabled"
|
||||
v-show="meta?.touched && errorMessage && !isDisabled"
|
||||
class="row mt-1 form-test-error">
|
||||
<span role="alert">{{ errorMessage }}</span>
|
||||
</div>
|
||||
|
|
@ -42,6 +43,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { dropdownVariants } from '@/constants/component-variants';
|
||||
import { useField } from 'vee-validate';
|
||||
|
||||
export default {
|
||||
|
|
@ -59,7 +61,11 @@ export default {
|
|||
validationRules: String,
|
||||
cmsWidgetName: String,
|
||||
hasError: Boolean,
|
||||
placeHolderText: String
|
||||
placeHolderText: String,
|
||||
variant: {
|
||||
type: String,
|
||||
default: dropdownVariants.primary
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
setup(props) {
|
||||
|
|
@ -154,5 +160,30 @@ export default {
|
|||
filter: grayscale(100%);
|
||||
}
|
||||
}
|
||||
&.dropdown-compact {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 1.25rem;
|
||||
.form-label {
|
||||
color: $darker-gray;
|
||||
font-weight: $font-weight-light;
|
||||
margin: 0;
|
||||
}
|
||||
.form-select {
|
||||
color: $heritage-blue-secondary;
|
||||
background-position-x: 98%;
|
||||
padding: 0;
|
||||
padding-left: .3125rem;
|
||||
width: 5.625rem;
|
||||
min-height: auto;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
&:focus,
|
||||
&:focus-visible {
|
||||
border: .125rem solid $black;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -13,19 +13,19 @@
|
|||
}">
|
||||
<div class="modal-dialog"
|
||||
:class="{
|
||||
'modal-dialog-edge': modalPosition === 'edge',
|
||||
'modal-dialog-centered': modalPosition === 'center'
|
||||
'modal-dialog-edge': modalPosition === modalPositions.edge,
|
||||
'modal-dialog-centered': modalPosition === modalPositions.center
|
||||
}">
|
||||
<div
|
||||
class="modal-content"
|
||||
role="dialog"
|
||||
aria-modal="true">
|
||||
<div class="modal-header mb-2 mt-2">
|
||||
<label
|
||||
<span
|
||||
v-if="headerText"
|
||||
class="modal-title d-flex justify-content-center pb-0 w-100">
|
||||
{{ headerText }}
|
||||
</label>
|
||||
class="modal-title d-flex justify-content-center pb-0 w-100"
|
||||
:innerHTML="headerText">
|
||||
</span>
|
||||
<button
|
||||
ref="closeButton"
|
||||
type="button"
|
||||
|
|
@ -60,6 +60,7 @@
|
|||
import ButtonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import { Modal } from 'bootstrap';
|
||||
import { useForm } from 'vee-validate';
|
||||
import { modalPositions } from '@/constants/component-variants';
|
||||
|
||||
export default {
|
||||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
|
|
@ -84,7 +85,11 @@ export default {
|
|||
},
|
||||
modalPosition: {
|
||||
type: String,
|
||||
default: 'edge'
|
||||
default: modalPositions.edge
|
||||
},
|
||||
allowInvalidSubmit: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
emits: ['footer-button-event', 'isModalOpened'],
|
||||
|
|
@ -102,7 +107,8 @@ export default {
|
|||
modalId,
|
||||
meta,
|
||||
validate,
|
||||
resetForm
|
||||
resetForm,
|
||||
modalPositions
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -121,7 +127,7 @@ export default {
|
|||
methods: {
|
||||
async validateAndEmit() {
|
||||
const validationResult = await this.validate();
|
||||
if (validationResult.valid) {
|
||||
if (validationResult.valid || this.allowInvalidSubmit) {
|
||||
this.$emit('footer-button-event');
|
||||
}
|
||||
},
|
||||
|
|
@ -257,6 +263,9 @@ export default {
|
|||
border-radius: 1.5rem;
|
||||
overflow: auto;
|
||||
}
|
||||
.modal-header {
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.show .modal-dialog {
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ export default {
|
|||
props: {
|
||||
customText: String, // used to allow the insert of token values into textblock
|
||||
justifyText: String, // left, right, center
|
||||
typeStyle: String, // h1-h6, body, small, label, caption
|
||||
typeStyle: String, // h1-h6, body, small, label, caption, disclaimer
|
||||
// (see Figma or Confluence documentation)
|
||||
fontWeight: String, // bold=500, default is 400
|
||||
cmsWidgetName: String,
|
||||
|
|
@ -109,5 +109,12 @@ export default {
|
|||
&.dark {
|
||||
color: $black;
|
||||
}
|
||||
&.disclaimer {
|
||||
color: $lighter-gray;
|
||||
font-weight: $font-weight-light;
|
||||
font-size: .8125rem;
|
||||
font-style: italic;
|
||||
margin-top: .625rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,8 @@
|
|||
class="input-wrapper"
|
||||
:class="[
|
||||
includeSearchIcon ? 'has-search-icon' : '',
|
||||
includeSelectIcon ? 'has-select-icon' : ''
|
||||
includeSelectIcon ? 'has-select-icon' : '',
|
||||
hasTextButton ? 'has-text-button' : ''
|
||||
]">
|
||||
<input
|
||||
:id="inputId"
|
||||
|
|
@ -61,6 +62,13 @@
|
|||
data-bs-toggle="modal"
|
||||
:data-bs-target="'#' + cmsWidgetName"
|
||||
aria-label="Select button" />
|
||||
<buttonMain
|
||||
v-if="hasTextButton"
|
||||
ref="buttonMain"
|
||||
variant="primary"
|
||||
:buttonText="buttonText"
|
||||
@clickEvent="clickedTextButton">
|
||||
</buttonMain>
|
||||
</div>
|
||||
<div
|
||||
v-show="errorMessage"
|
||||
|
|
@ -76,9 +84,13 @@
|
|||
<script>
|
||||
import { useField, validate } from 'vee-validate';
|
||||
import { extractSpanText } from '@/helpers/text-helper';
|
||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||
|
||||
export default {
|
||||
name: 'textbox-question',
|
||||
components: {
|
||||
buttonMain
|
||||
},
|
||||
props: {
|
||||
type: {
|
||||
type: String,
|
||||
|
|
@ -118,7 +130,11 @@ export default {
|
|||
includeSelectIcon: Boolean,
|
||||
min: String,
|
||||
max: String,
|
||||
disableAutoFill: Boolean
|
||||
disableAutoFill: Boolean,
|
||||
buttonCallback: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
}
|
||||
},
|
||||
emits: ['focus', 'update:modelValue', 'textboxQuestionEvent.inputIdAssigned', 'click-event'],
|
||||
setup(props) {
|
||||
|
|
@ -161,6 +177,12 @@ export default {
|
|||
questionTextForAria() {
|
||||
return extractSpanText(this.getCmsContent(this.cmsWidgetName, 'QuestionText'));
|
||||
},
|
||||
buttonText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'ButtonText');
|
||||
},
|
||||
hasTextButton() {
|
||||
return this.buttonText && this.buttonText.length > 0;
|
||||
},
|
||||
value: {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
|
|
@ -227,6 +249,13 @@ export default {
|
|||
if (this.meta.valid) {
|
||||
this.$emit('click-event');
|
||||
}
|
||||
},
|
||||
async clickedTextButton() {
|
||||
const result = await validate(this.value, this.validationRules);
|
||||
if (result.valid) {
|
||||
this.handleChange(this.value);
|
||||
this.$emit('click-event');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -273,7 +302,7 @@ input::-webkit-date-and-time-value {
|
|||
color: #4d5151;
|
||||
}
|
||||
.form-test-error span {
|
||||
color: #d4281c;
|
||||
color: $red;
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
|
@ -318,6 +347,19 @@ input::-webkit-date-and-time-value {
|
|||
display: flex;
|
||||
}
|
||||
}
|
||||
&.has-text-button {
|
||||
display: flex;
|
||||
input[type='text'] {
|
||||
border-radius: 1.5rem;
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
}
|
||||
button {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
min-width: 6.875rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
input {
|
||||
&.has-icon {
|
||||
|
|
@ -338,8 +380,8 @@ input::-webkit-date-and-time-value {
|
|||
.form-control {
|
||||
border: $border-input;
|
||||
border-radius: $border-radius;
|
||||
min-height: 3rem;
|
||||
max-height: 3rem;
|
||||
min-height: 2.8125rem;
|
||||
max-height: 2.8125rem;
|
||||
padding: 0.75rem 1rem;
|
||||
letter-spacing: inherit;
|
||||
box-shadow: $box-shadow-input;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ function processZipCodeResults(request) {
|
|||
containsMilitaryBase: serviceZipValidationResponse.containsMilitaryBase,
|
||||
isValid: serviceZipValidationResponse.isValid,
|
||||
isServiceable: serviceZipValidationResponse.isServiceable,
|
||||
city: serviceZipValidationResponse.city,
|
||||
state: serviceZipValidationResponse.state,
|
||||
zipCodeCtu: serviceZipValidationResponse.zipCodeCtu
|
||||
})).catch(() => ({
|
||||
|
|
|
|||
|
|
@ -45,11 +45,8 @@ export function createUnorderedListFromStringOfParagraphs(stringOfParagraphs) {
|
|||
* @returns {string}
|
||||
*/
|
||||
export function toTitleCase(text) {
|
||||
const temp = text?.toLowerCase()?.split(' ') ?? [];
|
||||
for (let i = 0; i < temp.length; i++) {
|
||||
temp[i] = temp[i].charAt(0).toUpperCase() + temp[i].slice(1);
|
||||
}
|
||||
return temp.join(' ');
|
||||
let temp = text?.toLowerCase() ?? '';
|
||||
return temp.replace(/(^|\s|-)\S/g, (letter) => letter.toUpperCase());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -314,7 +314,6 @@ describe('Google Map', () => {
|
|||
// Arrange
|
||||
const wrapper = shallowMount(googleMap, {});
|
||||
await awaitingSetupTicks(wrapper);
|
||||
const numberOfExtendCallsDuringMount = 2;
|
||||
|
||||
mockGeocode.mockImplementation(() => {
|
||||
const result = {
|
||||
|
|
@ -329,7 +328,7 @@ describe('Google Map', () => {
|
|||
const result = wrapper.vm.getBounds(locations);
|
||||
|
||||
// Assert
|
||||
expect(mockExtend).toHaveBeenCalledTimes(numberOfExtendCallsDuringMount + numberOfExtendCallsPostMount);
|
||||
expect(mockExtend).toHaveBeenCalledTimes(numberOfExtendCallsPostMount);
|
||||
expect(result).toBe(mockLatLngBound);
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export default {
|
|||
const { AdvancedMarkerElement, PinElement } = await window.google.maps.importLibrary('marker');
|
||||
markers?.forEach((marker, index) => {
|
||||
const pinElement = new PinElement({
|
||||
glyph: String.fromCharCode('A'.charCodeAt(0) + index),
|
||||
glyphText: String.fromCharCode('A'.charCodeAt(0) + index),
|
||||
glyphColor: '#000000',
|
||||
borderColor: '#000000'
|
||||
});
|
||||
|
|
@ -107,9 +107,11 @@ export default {
|
|||
async getBoundsFromAddress(address) {
|
||||
await this.setGeocoder();
|
||||
const result = await this.geocoder.geocode({ address });
|
||||
return result?.results?.length > 0
|
||||
? result.results[0].geometry?.bounds
|
||||
: null;
|
||||
if (result?.results?.length > 0) {
|
||||
return result.results[0].geometry?.bounds ?? null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
async createMapWithMarkersForAddresses(markers) {
|
||||
const markerPositions = await this.getLocationsFromAddresses(markers);
|
||||
|
|
@ -117,9 +119,12 @@ export default {
|
|||
const map = await this.getMap(zipBounds?.getCenter());
|
||||
|
||||
await this.addMarkersToMap(map, markerPositions);
|
||||
let positionsToDisplay = markerPositions.map((marker) => marker.position);
|
||||
if(zipBounds) {
|
||||
positionsToDisplay.push(zipBounds.getNorthEast());
|
||||
positionsToDisplay.push(zipBounds.getSouthWest());
|
||||
}
|
||||
|
||||
const positionsToDisplay = markerPositions.map((marker) => marker.position)
|
||||
.concat(zipBounds?.getNorthEast(), zipBounds?.getSouthWest());
|
||||
const bounds = this.getBounds(positionsToDisplay);
|
||||
map.fitBounds(bounds);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,13 +2,13 @@
|
|||
|
||||
exports[`Shop list button should render correctly with all relevant props 1`] = `
|
||||
<transition-stub name="fade" mode="out-in" appear="false" persisted="false" css="true" selectedvalue="selected value">
|
||||
<base-input-button-stub modelvalue="value of modal" groupname="name of group" buttonwrapperclasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2" ismultiselect="false" validationrules="" isrequired="true" selectinginitiatesload="false" suppresserror="false" buttonlabel="Label of button" buttonlabelsubcopy="Sub copy of button" buttonbodycopy="button body copy" screenreaderonlytext="screen reader only text" additionalbuttondata="[object Object]" alttext="" iswide="false" value="1234"></base-input-button-stub>
|
||||
<base-input-button-stub modelvalue="value of modal" groupname="name of group" buttonwrapperclasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 no-hover mb-2" ismultiselect="false" validationrules="" isrequired="true" selectinginitiatesload="false" suppresserror="false" buttonlabel="Label of button" buttonlabelsubcopy="Sub copy of button" buttonbodycopy="button body copy" screenreaderonlytext="screen reader only text" additionalbuttondata="[object Object]" alttext="" iswide="false" value="1234"></base-input-button-stub>
|
||||
</transition-stub>
|
||||
`;
|
||||
|
||||
exports[`Shop list button should render correctly with required props 1`] = `
|
||||
<transition-stub name="fade" mode="out-in" appear="false" persisted="false" css="true">
|
||||
<base-input-button-stub modelvalue="value of modal" groupname="name of group" buttonwrapperclasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2" ismultiselect="false" validationrules="" isrequired="true" selectinginitiatesload="false" suppresserror="false" alttext="" iswide="false" value="1234"></base-input-button-stub>
|
||||
<base-input-button-stub modelvalue="value of modal" groupname="name of group" buttonwrapperclasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 no-hover mb-2" ismultiselect="false" validationrules="" isrequired="true" selectinginitiatesload="false" suppresserror="false" alttext="" iswide="false" value="1234"></base-input-button-stub>
|
||||
</transition-stub>
|
||||
`;
|
||||
|
||||
|
|
|
|||
|
|
@ -149,10 +149,9 @@ describe('Shop list button', () => {
|
|||
|
||||
// Assert
|
||||
expect(buttonLabelSubCopy.exists()).toBeTruthy();
|
||||
expect(buttonLabelSubCopy.classes().length).toBe(4);
|
||||
expect(buttonLabelSubCopy.classes().length).toBe(3);
|
||||
expect(buttonLabelSubCopy.classes()).toContain('m-0');
|
||||
expect(buttonLabelSubCopy.classes()).toContain('caption');
|
||||
expect(buttonLabelSubCopy.classes()).toContain('ms-2');
|
||||
expect(buttonLabelSubCopy.classes()).toContain('button-label-sub-copy');
|
||||
expect(buttonLabelSubCopy.classes()).toContain(textPosition);
|
||||
});
|
||||
test('when "textPosition" prop not provided', async () => {
|
||||
|
|
@ -173,10 +172,9 @@ describe('Shop list button', () => {
|
|||
|
||||
// Assert
|
||||
expect(buttonLabelSubCopy.exists()).toBeTruthy();
|
||||
expect(buttonLabelSubCopy.classes().length).toBe(3);
|
||||
expect(buttonLabelSubCopy.classes().length).toBe(2);
|
||||
expect(buttonLabelSubCopy.classes()).toContain('m-0');
|
||||
expect(buttonLabelSubCopy.classes()).toContain('caption');
|
||||
expect(buttonLabelSubCopy.classes()).toContain('ms-2');
|
||||
expect(buttonLabelSubCopy.classes()).toContain('button-label-sub-copy');
|
||||
});
|
||||
});
|
||||
describe('availability indicator block with expected when displayAvailabilityIndicators true', () => {
|
||||
|
|
@ -378,8 +376,7 @@ describe('Shop list button', () => {
|
|||
// Assert
|
||||
expect(buttonBodyCopy.exists()).toBeTruthy();
|
||||
expect(buttonBodyCopy.classes()).toContain('m-0');
|
||||
expect(buttonBodyCopy.classes()).toContain('button-label-sub-copy');
|
||||
expect(buttonBodyCopy.classes()).toContain('small');
|
||||
expect(buttonBodyCopy.classes()).toContain('button-body-copy');
|
||||
});
|
||||
test('screen reader only text when screenReaderOnlyText provided', async () => {
|
||||
// Arrange
|
||||
|
|
|
|||
|
|
@ -5,35 +5,39 @@
|
|||
<baseInputButton
|
||||
v-bind="$props"
|
||||
v-model="selectedValue"
|
||||
buttonWrapperClasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 mb-2">
|
||||
buttonWrapperClasses="list-group base-input-button list-button rounded-3 d-flex flex-column w-100 no-hover mb-2">
|
||||
<div
|
||||
:aria-label="buttonLabel"
|
||||
class="button-content list-button-content d-flex flex-column justify-content-center py-3 px-4">
|
||||
<div class="row-one">
|
||||
<div class="availability-indicator-spacer"></div>
|
||||
<span
|
||||
id="buttonLabelSpan"
|
||||
class="m-0 button-label-copy"
|
||||
:class="textPosition">{{ buttonLabel }}
|
||||
</span>
|
||||
<span class="separator"></span>
|
||||
<span
|
||||
id="buttonLabelSubCopySpan"
|
||||
class="m-0 caption ms-2"
|
||||
class="m-0 button-label-sub-copy"
|
||||
:class="textPosition">{{ buttonLabelSubCopy }}
|
||||
</span>
|
||||
<div
|
||||
v-if="displayAvailabilityIndicators"
|
||||
id="availabilityIndicatorBlock"
|
||||
class="availability-indicator rounded-pill"
|
||||
:class="availabilityRatingClass">
|
||||
<div class="availability-indicator-container">
|
||||
<div
|
||||
id="availabilityIndicator"
|
||||
class="d-flex align-items-center">
|
||||
v-if="displayAvailabilityIndicators"
|
||||
id="availabilityIndicatorBlock"
|
||||
class="availability-indicator rounded-pill"
|
||||
:class="availabilityRatingClass">
|
||||
<div
|
||||
id="availabilityBadge"
|
||||
class="availability-badge"
|
||||
:class="availabilityRating == 'high' ? 'green' : 'orange'">
|
||||
id="availabilityIndicator"
|
||||
class="d-flex align-items-center">
|
||||
<div
|
||||
id="availabilityBadge"
|
||||
class="availability-badge"
|
||||
:class="availabilityRatingClass">
|
||||
</div>
|
||||
<span class="m-0 button-auxillary-copy">{{ badgeText }}</span>
|
||||
</div>
|
||||
<span class="m-0 button-auxillary-copy">{{ badgeText }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -41,7 +45,7 @@
|
|||
<span
|
||||
v-if="buttonBodyCopy"
|
||||
id="buttonBodyCopy"
|
||||
class="m-0 button-label-sub-copy small"
|
||||
class="m-0 button-body-copy"
|
||||
v-html="buttonBodyCopy"></span>
|
||||
</div>
|
||||
<span
|
||||
|
|
@ -103,116 +107,128 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/ux-variables-svg-strings.scss";
|
||||
$heritage-border-radius: 60px;
|
||||
$heritage-border-color: #CACBCC;
|
||||
$heritage-box-shadow: 0 1px 5px rgba($black, 0.2);
|
||||
$heritage-checked-background-color: #e7f1f6;
|
||||
$heritage-checked-border-color: #0070d1;
|
||||
|
||||
.list-button {
|
||||
outline: none;
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
position: static; //override bootstrap
|
||||
|
||||
&:focus-visible + .list-button-content {
|
||||
box-shadow: 0 0 0 2.5px $blue;
|
||||
}
|
||||
&:focus + .list-button-content {
|
||||
box-shadow: 0 0 0 2.5px $blue;
|
||||
}
|
||||
&:checked + .list-button-content {
|
||||
color: $black;
|
||||
font-weight: 500;
|
||||
background: $blue-100;
|
||||
box-shadow: 0 0 0 1px $blue;
|
||||
}
|
||||
&:checked:focus + .list-button-content {
|
||||
box-shadow: 0 0 0 2.5px $blue;
|
||||
}
|
||||
&:checked + .list-button-content p,
|
||||
&:checked + .list-button-content span {
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
outline: none;
|
||||
input[type="radio"],
|
||||
input[type="checkbox"] {
|
||||
position: static; //override bootstrap
|
||||
&:checked + .list-button-content {
|
||||
background: $heritage-checked-background-color;
|
||||
border-color: $heritage-checked-border-color;
|
||||
box-shadow: 0 0 0 1px $blue;
|
||||
.button-label-copy {
|
||||
font-weight: 500;
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
&:focus:checked + .list-button-content {
|
||||
border-width: 2.5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.list-button-content {
|
||||
color: $gray-600;
|
||||
position: relative;
|
||||
background: $white;
|
||||
transition: all 150ms linear;
|
||||
border-radius: $border-radius-lg;
|
||||
border: 1px solid $gray-500;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
|
||||
span {
|
||||
&.small {
|
||||
font-size: 0.75rem;
|
||||
color: $gray-550;
|
||||
}
|
||||
}
|
||||
color: $darker-gray;
|
||||
font-weight: $font-weight-normal;
|
||||
position: relative;
|
||||
background: $white;
|
||||
transition: all 150ms linear;
|
||||
border-radius: $heritage-border-radius;
|
||||
border: 1px solid $heritage-border-color;
|
||||
box-shadow: $heritage-box-shadow;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
}
|
||||
.button-content {
|
||||
row-gap: 0.25rem;
|
||||
row-gap: 0.25rem;
|
||||
|
||||
.row-one {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 1.5rem;
|
||||
.row-one {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
line-height: 1.5rem;
|
||||
|
||||
.button-label-copy {
|
||||
font-weight: 500;
|
||||
}
|
||||
.separator {
|
||||
height: 1.25rem;
|
||||
margin: 0rem .3125rem;
|
||||
border-left: 1px solid $heritage-border-color;
|
||||
}
|
||||
|
||||
.availability-indicator {
|
||||
background-repeat: no-repeat;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-left: auto;
|
||||
padding: 0.125rem 0.5rem;
|
||||
.availability-indicator-spacer {
|
||||
width: 8rem;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
.availability-badge {
|
||||
display: inline-flex;
|
||||
width: 13px;
|
||||
height: 12px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
margin: 0 0.25rem 0 0;
|
||||
.availability-indicator-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
margin-left: auto;
|
||||
width: 8rem;
|
||||
}
|
||||
|
||||
&.green {
|
||||
background-image: url($svg-shop-list-button-green-availability);
|
||||
}
|
||||
.availability-indicator {
|
||||
background-repeat: no-repeat;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.125rem 0.5rem;
|
||||
|
||||
&.orange {
|
||||
background-image: url($svg-shop-list-button-orange-availability);
|
||||
}
|
||||
}
|
||||
.button-auxillary-copy {
|
||||
box-sizing: border-box;
|
||||
justify-content: right;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
.availability-badge {
|
||||
display: inline-flex;
|
||||
width: 13px;
|
||||
height: 12px;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
margin: 0 0.25rem 0 0;
|
||||
|
||||
&.green {
|
||||
color: $green-700;
|
||||
background-color: $green-100;
|
||||
}
|
||||
&.green {
|
||||
background-image: url($svg-shop-list-button-green-availability);
|
||||
}
|
||||
|
||||
&.orange {
|
||||
color: $orange-600;
|
||||
background-color: $orange-100;
|
||||
}
|
||||
&.orange {
|
||||
background-image: url($svg-shop-list-button-orange-availability);
|
||||
}
|
||||
|
||||
&.gray {
|
||||
color: $gray-600;
|
||||
background-color: $gray-100;
|
||||
padding-left: 0.125rem;
|
||||
padding-right: 0.125rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.gray {
|
||||
background-image: url(~@/assets/img/heritage-loader-blue.gif);
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
||||
.button-auxillary-copy {
|
||||
box-sizing: border-box;
|
||||
justify-content: right;
|
||||
line-height: 1.25rem;
|
||||
font-weight: 500;
|
||||
font-size: 0.75rem;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.row-two {
|
||||
text-align: left;
|
||||
}
|
||||
&.green {
|
||||
color: $green-700;
|
||||
background-color: $green-100;
|
||||
}
|
||||
|
||||
&.orange {
|
||||
color: $orange-600;
|
||||
background-color: $orange-100;
|
||||
}
|
||||
|
||||
&.gray {
|
||||
color: $gray-600;
|
||||
background-color: $gray-100;
|
||||
padding-left: 0.125rem;
|
||||
padding-right: 0.125rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.row-two {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
|||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
import { buttonVariants } from '@/constants/component-variants';
|
||||
|
||||
// Supporting files
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper.js';
|
||||
|
|
@ -135,7 +135,8 @@ export default {
|
|||
* @summary Steps to perform when forward button clicked.
|
||||
*/
|
||||
async forwardButtonAction() {
|
||||
if (this.selectedAnswer == null) {
|
||||
// If user clicked foward without selecting an option or user click on "start a new claim" button.
|
||||
if (this.selectedAnswer == null || this.selectedAnswer === 'NewClaim') {
|
||||
this.navigateForward();
|
||||
return;
|
||||
}
|
||||
|
|
@ -154,6 +155,7 @@ export default {
|
|||
}
|
||||
},
|
||||
navigateForward() {
|
||||
this.mainStore.updateDuplicateCheckVisited(true);
|
||||
if (!this.mainStore.isPolicyLookupSuccessful) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
<siteSubHeader
|
||||
ref="siteSubHeader"
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-4" />
|
||||
class="site-sub-header-container" />
|
||||
<buttonQuestion
|
||||
v-if="educatorEndorsement"
|
||||
ref="schoolPropertyQuestion"
|
||||
|
|
@ -192,17 +192,147 @@ export default {
|
|||
min-height: 1px;
|
||||
padding-left: .9375rem;
|
||||
padding-right: .9375rem;
|
||||
|
||||
.windshield-chip-count-question {
|
||||
:deep(.col:first-of-type) {
|
||||
.list-button-horizontal {
|
||||
border-bottom-left-radius: $border-radius-list-button;
|
||||
border-top-left-radius: $border-radius-list-button;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.list-button-horizontal-content {
|
||||
border-bottom-left-radius: $border-radius-list-button;
|
||||
border-top-left-radius: $border-radius-list-button;
|
||||
border-right-width: 0;
|
||||
|
||||
span {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5rem;
|
||||
color: #525656;
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
.list-button-horizontal-content {
|
||||
span {
|
||||
color: #000;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.col:last-of-type) {
|
||||
.list-button-horizontal {
|
||||
border-bottom-right-radius: $border-radius-list-button;
|
||||
border-top-right-radius: $border-radius-list-button;
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.list-button-horizontal-content {
|
||||
border-bottom-right-radius: $border-radius-list-button;
|
||||
border-top-right-radius: $border-radius-list-button;
|
||||
|
||||
span {
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5rem;
|
||||
color: #525656;
|
||||
}
|
||||
}
|
||||
|
||||
&.selected {
|
||||
.list-button-horizontal-content {
|
||||
span {
|
||||
font-weight: 600;
|
||||
color: #000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.list-button-horizontal) {
|
||||
.list-button-horizontal-content {
|
||||
padding: 0.625rem;
|
||||
border: 1px solid #b3b4b5;
|
||||
height: 2.875rem;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
.list-button-horizontal-content {
|
||||
border: 1px solid #0070d1;
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
&:focus + .list-button-horizontal-content {
|
||||
box-shadow: none;
|
||||
border: 2.5px solid #0070d1;
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-error {
|
||||
border: none;
|
||||
.list-button-horizontal-content {
|
||||
border: 1px solid #db0020;
|
||||
}
|
||||
|
||||
input[type="radio"] {
|
||||
&:focus + .list-button-horizontal-content {
|
||||
border: 2.5px solid #db0020;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(fieldset) {
|
||||
box-shadow: 0 1px 5px rgba(0, 0, 0, .2);
|
||||
border-radius: $border-radius-list-button;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.question-text) {
|
||||
line-height: 1.5rem;
|
||||
margin-bottom: .3125rem;
|
||||
& > span {
|
||||
text-align: left;
|
||||
line-height: 1.5rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.subheader-primary) {
|
||||
margin-bottom: map-get($spacers, 2);
|
||||
line-height: 1.5rem;
|
||||
|
||||
h5 {
|
||||
line-height: 1.5rem;
|
||||
span {
|
||||
font-size: 1rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.subheader-secondary) {
|
||||
line-height: 1.5rem;
|
||||
margin-top: 0.625rem;
|
||||
p {
|
||||
font-size: $h6-font-size;
|
||||
line-height: map-get($spacers, 5);
|
||||
font-size: 1rem;
|
||||
font-weight: 400;
|
||||
line-height: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -213,18 +343,6 @@ export default {
|
|||
justify-content: left !important;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
margin-bottom: map-get($spacers, 5);
|
||||
}
|
||||
|
||||
:deep(.question-text) {
|
||||
& > span {
|
||||
text-align: left;
|
||||
line-height: map-get($spacers, 5);
|
||||
}
|
||||
margin-bottom: map-get($spacers, 2);
|
||||
}
|
||||
|
||||
:deep(div.question-text.d-flex) {
|
||||
margin-top: map-get($spacers, 4);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ describe('navigation', () => {
|
|||
expect(wrapper.vm.navigateForward).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
test('if the coverage policy verified navigate forward to policy-vehicle page', async () => {
|
||||
test('if the coverage policy verified navigate forward to vehicle damage page', async () => {
|
||||
// Arrange
|
||||
const mockRegistrationAddress = {
|
||||
streetAddress: '1234 Main St',
|
||||
|
|
@ -135,14 +135,6 @@ describe('navigation', () => {
|
|||
state: 'OH',
|
||||
zipCode: '43215'
|
||||
};
|
||||
const mockvehicles = [
|
||||
{
|
||||
vin: 'TEST_VIN'
|
||||
},
|
||||
{
|
||||
vin: 'TEST_VIN2'
|
||||
}
|
||||
];
|
||||
|
||||
const { wrapper } = setupMocks();
|
||||
|
||||
|
|
@ -152,13 +144,12 @@ describe('navigation', () => {
|
|||
customerQuestions: {
|
||||
addressQuestions: mockRegistrationAddress
|
||||
},
|
||||
isCoverageEnabled: true,
|
||||
vehiclesCount: 2,
|
||||
vehiclesFound: mockvehicles
|
||||
isCoverageEnabled: true
|
||||
});
|
||||
|
||||
useMainStore().order.policy.policyNumber = 'p_0001';
|
||||
useMainStore().order.policy.dateOfLoss = '2022-01-28';
|
||||
useMainStore().order.vehicle.policyVehicleId = 0;
|
||||
|
||||
// Act
|
||||
|
||||
|
|
@ -167,10 +158,111 @@ describe('navigation', () => {
|
|||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED,
|
||||
undefined,
|
||||
{},
|
||||
{},
|
||||
mockvehicles
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
test('if the coverage policy unverified navigate forward to vehicle damage page', async () => {
|
||||
// Arrange
|
||||
const mockRegistrationAddress = {
|
||||
streetAddress: '1234 Main St',
|
||||
city: 'Columbus',
|
||||
state: 'OH',
|
||||
zipCode: '43215'
|
||||
};
|
||||
|
||||
const { wrapper } = setupMocks();
|
||||
|
||||
await wrapper.setData({
|
||||
firstName: 'KK',
|
||||
lastName: 'KK',
|
||||
customerQuestions: {
|
||||
addressQuestions: mockRegistrationAddress
|
||||
},
|
||||
isCoverageEnabled: true
|
||||
});
|
||||
|
||||
useMainStore().order.policy.policyNumber = 'p_0001';
|
||||
useMainStore().order.policy.dateOfLoss = '2022-01-28';
|
||||
useMainStore().order.vehicle.policyVehicleId = null;
|
||||
|
||||
// Act
|
||||
|
||||
await wrapper.vm.forwardButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
undefined
|
||||
);
|
||||
});
|
||||
|
||||
test('if the coverage policy verified navigate back to welcome page', async () => {
|
||||
// Arrange
|
||||
const mockRegistrationAddress = {
|
||||
streetAddress: '1234 Main St',
|
||||
city: 'Columbus',
|
||||
state: 'OH',
|
||||
zipCode: '43215'
|
||||
};
|
||||
|
||||
const { wrapper } = setupMocks();
|
||||
|
||||
await wrapper.setData({
|
||||
firstName: 'KK',
|
||||
lastName: 'KK',
|
||||
customerQuestions: {
|
||||
addressQuestions: mockRegistrationAddress
|
||||
},
|
||||
isCoverageEnabled: true
|
||||
});
|
||||
|
||||
useMainStore().order.policy.policyNumber = 'p_0001';
|
||||
useMainStore().order.policy.dateOfLoss = '2022-01-28';
|
||||
useMainStore().order.vehicle.policyVehicleId = 0;
|
||||
|
||||
// Act
|
||||
|
||||
await wrapper.vm.backButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_POLICY_VERIFIED,
|
||||
undefined
|
||||
);
|
||||
});
|
||||
test('if the coverage policy unverified navigate back to vehicle-selection page', async () => {
|
||||
// Arrange
|
||||
const mockRegistrationAddress = {
|
||||
streetAddress: '1234 Main St',
|
||||
city: 'Columbus',
|
||||
state: 'OH',
|
||||
zipCode: '43215'
|
||||
};
|
||||
|
||||
const { wrapper } = setupMocks();
|
||||
|
||||
await wrapper.setData({
|
||||
firstName: 'KK',
|
||||
lastName: 'KK',
|
||||
customerQuestions: {
|
||||
addressQuestions: mockRegistrationAddress
|
||||
},
|
||||
isCoverageEnabled: true
|
||||
});
|
||||
|
||||
useMainStore().order.policy.policyNumber = 'p_0001';
|
||||
useMainStore().order.policy.dateOfLoss = '2022-01-28';
|
||||
useMainStore().order.vehicle.policyVehicleId = null;
|
||||
|
||||
// Act
|
||||
|
||||
await wrapper.vm.backButtonAction();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigate).toHaveBeenCalledWith(
|
||||
navigationScenarios.CLICKED_BACK_POLICY_UNVERIFIED,
|
||||
undefined
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@
|
|||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="!meta.valid"
|
||||
@ForwardClicked="forwardButtonAction"
|
||||
@backClicked="navigateBack" />
|
||||
@backClicked="backButtonAction" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -138,7 +138,6 @@ export default {
|
|||
data() {
|
||||
return {
|
||||
customerQuestions: this.getPolicyHolderDetailsFromStore(),
|
||||
vehiclesFound: [],
|
||||
rules: {
|
||||
firstName: globalRules.POLICYHOLDER_FIRST_NAME_REQUIRED,
|
||||
lastName: globalRules.POLICYHOLDER_LAST_NAME_REQUIRED,
|
||||
|
|
@ -152,8 +151,8 @@ export default {
|
|||
isCoverageEnabled() {
|
||||
return this.mainStore.issConfig.isCoverageEnabled;
|
||||
},
|
||||
vehiclesCount() {
|
||||
return this.vehiclesFound.length;
|
||||
isPolicyVehicleSelected() {
|
||||
return (this.mainStore.order.vehicle.policyVehicleId != null && this.mainStore.order.vehicle.policyVehicleId >= 0);
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -163,13 +162,10 @@ export default {
|
|||
},
|
||||
|
||||
navigateForward() {
|
||||
if (this.vehiclesCount > 0) {
|
||||
if (this.isPolicyVehicleSelected) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED,
|
||||
this.$route,
|
||||
{},
|
||||
{},
|
||||
this.vehiclesFound
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
|
|
@ -179,6 +175,20 @@ export default {
|
|||
}
|
||||
},
|
||||
|
||||
backButtonAction() {
|
||||
if (this.isPolicyVehicleSelected) {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_BACK_POLICY_VERIFIED,
|
||||
this.$route
|
||||
);
|
||||
} else {
|
||||
this.$router.navigate(
|
||||
this.navigationScenarios.CLICKED_BACK_POLICY_UNVERIFIED,
|
||||
this.$route
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
getPolicyHolderDetailsFromStore() {
|
||||
return {
|
||||
addressQuestions: {
|
||||
|
|
@ -194,7 +204,7 @@ export default {
|
|||
lastName: this.mainStore.order.customer.lastName,
|
||||
phoneNumber: this.mainStore.order.contactInfo.homePhone,
|
||||
extension: this.mainStore.order.contactInfo.extension,
|
||||
email: this.mainStore.order.customer.emailAddress,
|
||||
email: this.mainStore.order.customer.emailAddress
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ import coverageType from '@/constants/coverage-type';
|
|||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
import { buttonVariants } from '@/constants/component-variants';
|
||||
|
||||
export default {
|
||||
name: 'policy-vehicles',
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
v-html="scheduleWithOtherText"></div>
|
||||
<textLink
|
||||
class="underlined-text"
|
||||
linkType="navigation"
|
||||
linkType="text"
|
||||
text="Find another shop"
|
||||
href="#"
|
||||
@clickEvent="findAnotherShopClicked" />
|
||||
|
|
|
|||
|
|
@ -1,24 +1,21 @@
|
|||
<template>
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
v-if="isDisplayed"
|
||||
class="appointment-type-question"
|
||||
aria-live="polite">
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-model="selectedValues"
|
||||
customButtonQuestionId="appointmentTypeQuestion"
|
||||
:questionText="questionText"
|
||||
:answers="answersToDisplay"
|
||||
:groupName="groupName"
|
||||
buttonTypeString="listCard"
|
||||
:suppressError="suppressError"
|
||||
:validationRules="validationRules"
|
||||
isRequired />
|
||||
</div>
|
||||
</transition>
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
class="appointment-type-question"
|
||||
aria-live="polite">
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-model="selectedValues"
|
||||
customButtonQuestionId="appointmentTypeQuestion"
|
||||
:answers="answersToDisplay"
|
||||
:groupName="groupName"
|
||||
:suppressError="suppressError"
|
||||
:validationRules="validationRules"
|
||||
isRequired />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
|
@ -38,12 +35,9 @@ export default {
|
|||
modelValue: String,
|
||||
groupName: String,
|
||||
isAvailable: Boolean,
|
||||
isDisplayed: Boolean,
|
||||
suppressError: Boolean,
|
||||
validationRules: String,
|
||||
cmsWidgetName: String,
|
||||
isServiceableMobile: Boolean,
|
||||
isServiceableInshop: Boolean
|
||||
cmsWidgetName: String
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
computed: {
|
||||
|
|
@ -51,23 +45,13 @@ export default {
|
|||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||
},
|
||||
answersFromCms() {
|
||||
const retCms = this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
if (retCms && retCms.length > 0 && this.isMobileFeeHidden) {
|
||||
return retCms.map((x) => (x.Name === AppointmentTypeStrings.MOBILE ? { ...x, SubText: x.SubText.replace('*', '') } : x));
|
||||
}
|
||||
return retCms;
|
||||
return this.getCmsContent(this.cmsWidgetName, 'Answers');
|
||||
},
|
||||
answersToDisplay() {
|
||||
const shouldShowMobile = this.isServiceableMobile && this.isItacOrNoComp;
|
||||
const shouldShowMobileNotITACNotNoComp = this.isServiceableMobile && !this.isItacOrNoComp;
|
||||
const shouldShowInshop = this.isServiceableInshop;
|
||||
const shouldShowDropoff = this.isServiceableInshop && !useMainStore().damage.isRepair;
|
||||
return this.answersFromCms
|
||||
? this.answersFromCms.filter((answer) => (
|
||||
(answer.Name === AppointmentTypeStrings.IN_SHOP && shouldShowInshop)
|
||||
|| (answer.Name === AppointmentTypeStrings.MOBILE && shouldShowMobile)
|
||||
|| (answer.Name === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP && shouldShowMobileNotITACNotNoComp)
|
||||
|| (answer.Name === AppointmentTypeStrings.DROP_OFF && shouldShowDropoff)
|
||||
(answer.Name === AppointmentTypeStrings.IN_SHOP)
|
||||
|| (answer.Name === AppointmentTypeStrings.MOBILE)
|
||||
))
|
||||
: [];
|
||||
},
|
||||
|
|
@ -78,58 +62,13 @@ export default {
|
|||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
},
|
||||
isITAC() {
|
||||
return useMainStore().isITAC;
|
||||
},
|
||||
isItacOrNoComp() {
|
||||
return this.isITAC || useMainStore().isNoComp;
|
||||
},
|
||||
isMobileFeeHidden() {
|
||||
return this.getSettingValue(experimentSettings.ISS_FEATURE_TOGGLE_IS_MOBILE_FEE_HIDDEN) === 'true';
|
||||
},
|
||||
isMobileOnly() {
|
||||
return this.isServiceableMobile && !this.isServiceableInshop;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
answersToDisplay: {
|
||||
handler(newValue) {
|
||||
// If there is only one option to display and that option is 'Mobile' then select it
|
||||
if (
|
||||
newValue.length === 1
|
||||
&& newValue.findIndex((answer) => (answer.Name === AppointmentTypeStrings.MOBILE
|
||||
|| answer.Name === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP)) !== -1
|
||||
) {
|
||||
if (this.isItacOrNoComp) {
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE;
|
||||
} else {
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
}
|
||||
}
|
||||
},
|
||||
immediate: true
|
||||
},
|
||||
isMobileOnly: {
|
||||
handler(newValue) {
|
||||
if (newValue) {
|
||||
if (this.isItacOrNoComp) {
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE;
|
||||
} else {
|
||||
this.selectedValues = AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
:deep(.button-question) {
|
||||
.list-card img {
|
||||
height: auto;
|
||||
width: 3.417rem;
|
||||
}
|
||||
.appointment-type-question {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,29 +1,13 @@
|
|||
/* eslint-env jest */
|
||||
import baseMixin from '@/mixins/base-mixin';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import { mount, flushPromises } from '@vue/test-utils';
|
||||
import { createTestingPinia } from '@pinia/testing';
|
||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants';
|
||||
import navigationScenarios from '@/router/router-constants/navigation-scenarios';
|
||||
import routerParams from '@/router/router-constants/router-params';
|
||||
import { useMainStore } from '@/store';
|
||||
import serviceLocation from '@/layouts/service-location/service-location.vue';
|
||||
|
||||
// Define Mocks
|
||||
jest.mock('@/helpers/cms-content-helper', () => ({
|
||||
fetchCmsContentForPage: jest.fn(() => Promise.resolve('content'))
|
||||
}));
|
||||
|
||||
/** @ignore */
|
||||
function setupMocks() {
|
||||
const wrapper = shallowMount(
|
||||
serviceLocation,
|
||||
getMountOptions({
|
||||
router: {
|
||||
navigate: jest.fn()
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
wrapper.vm.$router.navigateWithSpinner = jest.fn();
|
||||
wrapper.vm.navigateBack = baseMixin.methods.navigateBack;
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
import { getZipCodeData } from '@/helpers/service-location-helper';
|
||||
|
||||
const mockGetServiceabilityDetails = () => {
|
||||
const serviceabilityDetails = {
|
||||
|
|
@ -35,123 +19,199 @@ const mockGetServiceabilityDetails = () => {
|
|||
|
||||
return Promise.resolve(serviceabilityDetails);
|
||||
};
|
||||
const mockZipcodeData = (zip) => {
|
||||
if (zip === '43235' || zip === '55555') {
|
||||
return Promise.resolve({
|
||||
containsMilitaryBase: false,
|
||||
isValid: true,
|
||||
isServiceable: true,
|
||||
city: 'Columbus',
|
||||
state: 'OH',
|
||||
zipCodeCtu: '01820'
|
||||
});
|
||||
}
|
||||
|
||||
if (zip === '45433') {
|
||||
return Promise.resolve({
|
||||
containsMilitaryBase: true,
|
||||
isValid: true,
|
||||
isServiceable: true,
|
||||
city: 'Columbus',
|
||||
state: 'OH',
|
||||
zipCodeCtu: '01820'
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
containsMilitaryBase: false,
|
||||
isValid: false,
|
||||
isServiceable: false,
|
||||
city: null,
|
||||
state: null,
|
||||
zipCodeCtu: null
|
||||
});
|
||||
}
|
||||
const mockProviders = () => {
|
||||
return Promise.resolve([
|
||||
{
|
||||
"address": {
|
||||
"city": "COLUMBUS",
|
||||
"country": "US",
|
||||
"state": "OH",
|
||||
"streetAddress": "6826 Sawmill Rd",
|
||||
"streetAddress2": "",
|
||||
"zipCode": "43235",
|
||||
"zipCodeCtu": "03357"
|
||||
},
|
||||
"distanceInMiles": 4.136335989015438,
|
||||
"providerNumber": "003357",
|
||||
"companyName": "SAFELITE AUTOGLASS - COLUMBUS, OH",
|
||||
"phoneNumber": "6142336400",
|
||||
"isSafeliteShop": true
|
||||
},
|
||||
{
|
||||
"address": {
|
||||
"city": "Lewis Center",
|
||||
"country": "US",
|
||||
"state": "OH",
|
||||
"streetAddress": "1343 Cameron Ave",
|
||||
"streetAddress2": "",
|
||||
"zipCode": "43035",
|
||||
"zipCodeCtu": "03357"
|
||||
},
|
||||
"distanceInMiles": 8.193072412262042,
|
||||
"providerNumber": "003417",
|
||||
"companyName": "SAFELITE AUTOGLASS - LEWIS CENTER, OH",
|
||||
"phoneNumber": "6147815433",
|
||||
"isSafeliteShop": true
|
||||
}
|
||||
])
|
||||
}
|
||||
jest.mock(
|
||||
'@/helpers/service-location-helper',
|
||||
() => ({
|
||||
getServiceabilityDetails: jest.fn((mockServiceZipCode) => mockGetServiceabilityDetails(mockServiceZipCode))
|
||||
getServiceabilityDetails: jest.fn((mockServiceZipCode) => mockGetServiceabilityDetails(mockServiceZipCode)),
|
||||
getZipCodeData: jest.fn((mockServiceZipCode) => mockZipcodeData(mockServiceZipCode)),
|
||||
getMobileZipCodeData: jest.fn((mockServiceZipCode) => mockZipcodeData(mockServiceZipCode))
|
||||
})
|
||||
);
|
||||
|
||||
const mockMixin = {
|
||||
methods: {
|
||||
getCmsContent: jest.fn((widgetName, cmsFieldName) => {
|
||||
// linkWidgetName is not defined. This whole spec file needs review.
|
||||
if (widgetName === linkWidgetName) {
|
||||
return mockLinkCmsContent[cmsFieldName];
|
||||
const mockRoute = {
|
||||
params: {}
|
||||
};
|
||||
const mockRouter = {
|
||||
navigate: jest.fn()
|
||||
};
|
||||
const mountOptions = {
|
||||
global: {
|
||||
mixins: [
|
||||
{
|
||||
computed: {
|
||||
navigationScenarios() {
|
||||
return navigationScenarios;
|
||||
},
|
||||
routerParams() {
|
||||
return routerParams;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getCmsContent: jest.fn(),
|
||||
getFooterInfoBoxHeight: jest.fn(() => 80),
|
||||
getPageNameByQueryString: jest.fn(() => '')
|
||||
}
|
||||
}
|
||||
|
||||
if (widgetName === modalWidgetName) {
|
||||
return mockModalCmsContent[cmsFieldName];
|
||||
}
|
||||
|
||||
return null;
|
||||
}),
|
||||
|
||||
getZipCodeData: jest.fn((zip) => {
|
||||
if (zip === '43235' || zip === '55555') {
|
||||
return Promise.resolve({
|
||||
containsMilitaryBase: false,
|
||||
isValid: true,
|
||||
state: 'OH',
|
||||
zipCodeCtu: '01820'
|
||||
});
|
||||
}
|
||||
|
||||
if (zip === '45433') {
|
||||
return Promise.resolve({
|
||||
containsMilitaryBase: true,
|
||||
isValid: true,
|
||||
state: 'OH'
|
||||
});
|
||||
}
|
||||
|
||||
return Promise.resolve({
|
||||
containsMilitaryBase: false,
|
||||
isValid: false,
|
||||
state: null,
|
||||
zipCodeCtu: null
|
||||
});
|
||||
}),
|
||||
|
||||
onSubmit: jest.fn(),
|
||||
onInvalidSubmit: jest.fn()
|
||||
],
|
||||
mocks: {
|
||||
$route: mockRoute,
|
||||
$router: mockRouter
|
||||
},
|
||||
stubs: {
|
||||
alert: true,
|
||||
textBlock: true,
|
||||
appointmentTypeQuestion: true,
|
||||
contentGroupModal: true,
|
||||
siteFooter: true,
|
||||
siteHeader: true,
|
||||
siteSubHeader: true,
|
||||
shopAddress: true,
|
||||
serviceZipQuestion: true
|
||||
}
|
||||
}
|
||||
};
|
||||
function setupMocks({ appointmentType = AppointmentTypeStrings.IN_SHOP }) {
|
||||
mountOptions.global.plugins = [createTestingPinia({
|
||||
initialState: {
|
||||
main: {
|
||||
order: {
|
||||
serviceLocation: {
|
||||
appointmentType: appointmentType
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})];
|
||||
useMainStore().getProviders = jest.fn().mockImplementation(() => mockProviders());
|
||||
const wrapper = mount(serviceLocation, mountOptions);
|
||||
|
||||
describe('navigation', () => {
|
||||
test('if the back button is clicked, navigate back', async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({
|
||||
wrapper.vm.$router.navigateWithSpinner = jest.fn();
|
||||
wrapper.vm.navigateBack = baseMixin.methods.navigateBack;
|
||||
|
||||
return { wrapper };
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
describe('service-location.vue', () => {
|
||||
describe('navigation', () => {
|
||||
test('if the back button is clicked, navigate back', async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({
|
||||
});
|
||||
|
||||
// Act
|
||||
await wrapper.vm.navigateBack();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSpinner).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
describe('updating service zip', () => {
|
||||
test('updates the page model after changing the service zip code', () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ appointmentType: AppointmentTypeStrings.IN_SHOP });
|
||||
|
||||
const newServiceZipCode = '61606';
|
||||
|
||||
const shopAddressComponent = wrapper.findComponent({
|
||||
ref: 'shopAddress'
|
||||
});
|
||||
|
||||
// Act
|
||||
shopAddressComponent.vm.$emit('zip-updated', newServiceZipCode);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.zipCode).toStrictEqual(newServiceZipCode);
|
||||
});
|
||||
|
||||
// Act
|
||||
await wrapper.vm.navigateBack();
|
||||
test('displays military zip message when zip is updated', async () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({ appointmentType: AppointmentTypeStrings.MOBILE });
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.$router.navigateWithSpinner).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('updating service zip', () => {
|
||||
test('updates the page model after changing the service zip code', () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({
|
||||
mixins: [mockMixin]
|
||||
});
|
||||
|
||||
const newServiceZipCodeQuestion = {
|
||||
zipCode: '61606',
|
||||
state: 'IL'
|
||||
};
|
||||
|
||||
const serviceZipCodeComponent = wrapper.findComponent({
|
||||
ref: 'serviceZipCodeQuestion'
|
||||
});
|
||||
|
||||
// Act
|
||||
serviceZipCodeComponent.vm.$emit('update:modelValue', newServiceZipCodeQuestion);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.serviceZipCodeQuestion).toStrictEqual(newServiceZipCodeQuestion);
|
||||
});
|
||||
|
||||
test('displays military zip message when zip is updated', () => {
|
||||
// Arrange
|
||||
const { wrapper } = setupMocks({});
|
||||
|
||||
const mobileLocationQuestionsComponent = wrapper.findComponent({
|
||||
ref: 'mobileLocationQuestions'
|
||||
});
|
||||
mobileLocationQuestionsComponent.resetComponent = jest.fn();
|
||||
|
||||
const serviceZipCodeComponent = wrapper.findComponent({
|
||||
ref: 'serviceZipCodeQuestion'
|
||||
});
|
||||
serviceZipCodeComponent.resetMobileFeePart = jest.fn();
|
||||
|
||||
expect(wrapper.vm.zipContainsMilitaryBase).toBe(false);
|
||||
|
||||
// TODO: Use or remove
|
||||
const newServiceZipCodeQuestion = {
|
||||
zipCode: '45433',
|
||||
state: 'OH'
|
||||
};
|
||||
|
||||
// Act
|
||||
serviceZipCodeComponent.vm.$emit('updated-contains-military-base', true);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.zipContainsMilitaryBase).toBe(true);
|
||||
const mobileServiceZipCodeQuestion = wrapper.findComponent({
|
||||
ref: 'mobileServiceZipCodeQuestion'
|
||||
});
|
||||
|
||||
expect(wrapper.vm.zipContainsMilitaryBase).toBe(false);
|
||||
|
||||
const newMobileServiceZipCode = '45433'
|
||||
|
||||
// Act
|
||||
mobileServiceZipCodeQuestion.vm.$emit('update:modelValue', newMobileServiceZipCode);
|
||||
await wrapper.vm.$nextTick();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.zipContainsMilitaryBase).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -12,28 +12,7 @@
|
|||
<div class="service-location-container iss-heritage-content-container-width">
|
||||
<siteSubHeader
|
||||
cmsWidgetName="SiteSubHeaderWidget"
|
||||
class="mt-4" />
|
||||
<serviceZipModalQuestion
|
||||
ref="serviceZipCodeQuestion"
|
||||
v-model="serviceZipCodeQuestion"
|
||||
modalWidgetName="ServiceZipModalWidget"
|
||||
:onZipUpdateCallback="reloadShopData"
|
||||
@updatedServiceability="setServiceabilityDetails"
|
||||
@updatedContainsMilitaryBase="
|
||||
setContainsMilitaryBase
|
||||
" />
|
||||
<alert
|
||||
v-if="displayMilitaryZipAlert"
|
||||
ref="alertMilitaryBaseZip"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMilitaryBaseZipWidget"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayServiceableMobileOnly"
|
||||
ref="alertMobileOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertMobileOnlyWidget"
|
||||
alertClass="alert-warning" />
|
||||
class="subheader" />
|
||||
<alert
|
||||
v-if="displayRecalibrationWarning"
|
||||
ref="alertRecalNoMobile"
|
||||
|
|
@ -41,18 +20,6 @@
|
|||
cmsWidgetName="AlertRecalNoMobileWidget"
|
||||
alertClass="alert-warning"
|
||||
@text-link-clicked="openModalAction" />
|
||||
<alert
|
||||
v-if="displayServiceableInshopOnly"
|
||||
ref="alertInshopOnly"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertInshopOnlyWidget"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayNoShopsAlert"
|
||||
ref="alertNoShops"
|
||||
class="my-5"
|
||||
cmsWidgetName="AlertNoShopsWidget"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayBigTruckNoShops"
|
||||
ref="alertBigTruckNoShops"
|
||||
|
|
@ -60,41 +27,94 @@
|
|||
cmsWidgetName="AlertBigTruckNoShopsWidget"
|
||||
alertClass="alert-warning" />
|
||||
<div class="appointment-type">
|
||||
<div class="appointment-type-question-text d-flex">
|
||||
<span class="w-100 recal-text" v-if="recalibrationRequired">{{ scheduleRecalText }}</span>
|
||||
<span class="w-100" v-if="!requiresInshopRecalibration">{{ appointmentQuestionText }}</span>
|
||||
</div>
|
||||
<alert
|
||||
v-if="displayServiceableInshopOnly"
|
||||
ref="alertInshopOnly"
|
||||
cmsWidgetName="AlertInshopOnlyWidget"
|
||||
:manualCopy="inShopOnlyCopy"
|
||||
:isCollapsible="true"
|
||||
alertClass="alert-warning" />
|
||||
<alert
|
||||
v-if="displayServiceableMobileOnly"
|
||||
ref="alertMobileOnly"
|
||||
cmsWidgetName="AlertMobileOnlyWidget"
|
||||
:manualCopy="mobileOnlyCopy"
|
||||
:isCollapsible="true"
|
||||
alertClass="alert-warning" />
|
||||
<appointmentTypeQuestion
|
||||
v-show="isAppointmentTypeDisplayed"
|
||||
v-if="!requiresInshopRecalibration && isServiceableMobile"
|
||||
ref="appointmentTypeQuestion"
|
||||
v-model="selectedAppointmentType"
|
||||
:isServiceableMobile="isServiceableMobile"
|
||||
:isServiceableInshop="isServiceableInshop"
|
||||
:isDisplayed="isAppointmentTypeDisplayed"
|
||||
groupName="appointmentTypeQuestion"
|
||||
cmsWidgetName="AppointmentTypeQuestionWidget"
|
||||
validationRules="option-required" />
|
||||
</div>
|
||||
<mobileLocationModalQuestions
|
||||
v-if="isMobileLocationDisplayed"
|
||||
ref="mobileLocationQuestions"
|
||||
v-model="mobileLocationQuestions"
|
||||
customComponentId="mobileLocationQuestions"
|
||||
:mobileFeePart="mobileFeePart"
|
||||
validationRules="mobile-location-required"
|
||||
linkWidgetName="MobileLocationLinkWidget"
|
||||
modalWidgetName="MobileLocationModalWidget"
|
||||
:onZipUpdateCallback="reloadShopData"
|
||||
@updated-mobile-fee-part="setMobileFeePart"
|
||||
@updated-serviceability="setServiceabilityDetails"
|
||||
@updated-contains-military-base="setContainsMilitaryBase"
|
||||
@updated-mobile-ctu="setCtuForMobile" />
|
||||
<shopQuestion
|
||||
v-show="isShopQuestionDisplayed"
|
||||
:ref="SHOP_QUESTION_REF_NAME"
|
||||
v-model="selectedProvider"
|
||||
:selectedAppointmentType="selectedAppointmentType"
|
||||
:isDisplayed="isShopQuestionDisplayed"
|
||||
cmsWidgetName="ShopQuestionWidget"
|
||||
@updatedMobileProviderNumber="
|
||||
setMobileProviderNumber
|
||||
" />
|
||||
<div
|
||||
v-if="isInshop">
|
||||
<alert
|
||||
v-if="displayLowAvailabilityInshop"
|
||||
ref="alertLowAvailabilityInshop"
|
||||
cmsWidgetName="AlertLowAvailabilityInshopWidget"
|
||||
:isCollapsible="true"
|
||||
alertClass="alert-warning" />
|
||||
<shopAddress
|
||||
ref="shopAddress"
|
||||
v-model="selectedProvider"
|
||||
:serviceZipcode="zipCode"
|
||||
:selectedAppointmentType="selectedAppointmentType"
|
||||
modalWidgetName="ChangeLocationModalWidget"
|
||||
cmsWidgetName="ShopAddressWidget"
|
||||
@zip-updated="handleInShopZipUpdated" />
|
||||
<!-- INTEGRATION TODO: Put this right under the calendar -->
|
||||
<alert
|
||||
v-if="selectedProvider === null"
|
||||
ref="alertNoAvailableShops"
|
||||
cmsWidgetName="AlertNoAvailableShopsWidget"
|
||||
:isCollapsible="true"
|
||||
alertClass="alert-danger" />
|
||||
</div>
|
||||
<div
|
||||
v-if="isMobile">
|
||||
<div class="expandable-link-container">
|
||||
<a
|
||||
v-if="displayMilitaryZipAlert && !militaryBaseWarningExpanded"
|
||||
href="#"
|
||||
class="expandable-link"
|
||||
@click.prevent="militaryBaseWarningExpanded = true">
|
||||
{{ militaryBaseWarningLinkText }}
|
||||
</a>
|
||||
<div
|
||||
v-if="displayMilitaryZipAlert && militaryBaseWarningExpanded"
|
||||
class="expandable-link-text">
|
||||
{{ militaryBaseWarningText }}
|
||||
</div>
|
||||
</div>
|
||||
<serviceZipQuestion
|
||||
ref="mobileServiceZipCodeQuestion"
|
||||
v-model="mobileZipCode"
|
||||
customInputId="mobileServiceZipCode"
|
||||
class="mobile-service-zip-question"
|
||||
:placeholderText="mobileZipPlaceholder"
|
||||
:serviceZipFormatErrorMessage="errorMessages.MOBILE_SERVICE_ZIP_FORMAT"
|
||||
:hasError="mobileZipError !== ''"
|
||||
cmsWidgetName="MobileZipWidget" />
|
||||
<div
|
||||
v-if="mobileZipError"
|
||||
ref="errorMessageDiv"
|
||||
class="row my-1 form-test-error">
|
||||
<span
|
||||
class="d-inline-flex mt-0"
|
||||
role="alert">{{ mobileZipError }}</span>
|
||||
</div>
|
||||
<textBlock
|
||||
v-if="displayMobileFeeDisclaimer"
|
||||
cmsWidgetName="MobileFeeDisclaimerWidget"
|
||||
typeStyle="disclaimer" />
|
||||
</div>
|
||||
<contentGroupModal
|
||||
:ref="RECAL_MODAL_REF_NAME"
|
||||
cssModalHeadlineClass="text-center"
|
||||
|
|
@ -104,7 +124,7 @@
|
|||
class="mt-5"
|
||||
cmsWidgetName="SiteFooterWidget"
|
||||
:isForwardActionDisabled="
|
||||
!meta.valid || displayNoShopsAlert
|
||||
!meta.valid || displayNoShopsAlert || displayBigTruckNoShops
|
||||
"
|
||||
@backClicked="navigateBack(this, navigateBackScenario)"
|
||||
@forwardClicked="forwardButtonAction" />
|
||||
|
|
@ -118,44 +138,31 @@
|
|||
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
||||
import { fetchCmsContentForPage } from '@/helpers/cms-content-helper';
|
||||
import settleAllPromises from '@/helpers/layout-helper';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import { useMainStore } from '@/store';
|
||||
import {
|
||||
getPricedMobileFeePart,
|
||||
getServiceabilityDetails,
|
||||
getZipCodeData
|
||||
getZipCodeData,
|
||||
getMobileZipCodeData
|
||||
} from '@/helpers/service-location-helper';
|
||||
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||
import { getAvailabilityRating } from '@/helpers/service-location-helper';
|
||||
|
||||
// Import Component
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||
import appointmentTypeQuestion from '@/layouts/service-location/appointment-type-question/appointment-type-question.vue';
|
||||
import baseFormMixin from '@/mixins/base-form-mixin';
|
||||
import contentGroupModal from '@/iss-components/content-group-modal/content-group-modal.vue';
|
||||
import mobileLocationModalQuestions from '@/layouts/service-location/mobile-location-modal-questions/mobile-location-modal-questions.vue';
|
||||
import { Form, defineRule } from 'vee-validate';
|
||||
import shopQuestion from '@/layouts/service-location/shop-question/shop-question.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import siteHeader from '@/iss-components/site-header/site-header.vue';
|
||||
import siteSubHeader from '@/iss-components/site-sub-header/site-sub-header.vue';
|
||||
import serviceZipModalQuestion from '@/layouts/service-location/service-zip-modal-question/service-zip-modal-question.vue';
|
||||
import shopAddress from '@/layouts/service-location/shop-address/shop-address.vue';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
||||
import widgetFields from '@/constants/cms-widget-fields';
|
||||
|
||||
// DEFINE VALIDATION RULES
|
||||
defineRule('mobile-location-required', (value) => {
|
||||
if (
|
||||
value.addressQuestions.streetAddress === ''
|
||||
|| value.addressQuestions.city === ''
|
||||
|| value.addressQuestions.state === ''
|
||||
|| value.addressQuestions.zipCode === ''
|
||||
|| value.isVehicleProtected == null
|
||||
) {
|
||||
return errorMessages.MOBILE_LOCATION_REQUIRED;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
defineRule('selection-required', required(errorMessages.OPTION_REQUIRED));
|
||||
|
||||
const SHOP_QUESTION_REF_NAME = 'shopQuestion';
|
||||
const RECAL_MODAL_REF_NAME = 'RecalModal';
|
||||
const SITE_FOOTER_REF_NAME = 'siteFooter';
|
||||
|
||||
|
|
@ -163,16 +170,16 @@ export default {
|
|||
name: 'service-location',
|
||||
components: {
|
||||
alert,
|
||||
textBlock,
|
||||
appointmentTypeQuestion,
|
||||
contentGroupModal,
|
||||
mobileLocationModalQuestions,
|
||||
siteFooter,
|
||||
siteHeader,
|
||||
siteSubHeader,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form,
|
||||
serviceZipModalQuestion,
|
||||
shopQuestion
|
||||
shopAddress,
|
||||
serviceZipQuestion
|
||||
},
|
||||
mixins: [baseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -182,8 +189,8 @@ export default {
|
|||
const zipCodeData = getZipCodeData(serviceZipCode);
|
||||
const mobileFeePartPromise = getPricedMobileFeePart(serviceZipCode);
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(serviceZipCode);
|
||||
const shopQuestionInitialDataPromise = shopQuestion.methods.loadInitialData(serviceZipCode);
|
||||
const getGlassFeesPromise = useMainStore().getGlassFees();
|
||||
const providersPromise = useMainStore().getProviders(serviceZipCode);
|
||||
|
||||
// Settle promises and get results
|
||||
const promiseResultMap = [
|
||||
|
|
@ -203,13 +210,13 @@ export default {
|
|||
resultKey: 'serviceabilityDetails',
|
||||
promise: serviceabilityDetailsPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'shopQuestionInitialData',
|
||||
promise: shopQuestionInitialDataPromise
|
||||
},
|
||||
{
|
||||
resultKey: 'zipCodeData',
|
||||
promise: zipCodeData
|
||||
},
|
||||
{
|
||||
resultKey: 'providers',
|
||||
promise: providersPromise
|
||||
}
|
||||
];
|
||||
|
||||
|
|
@ -221,10 +228,9 @@ export default {
|
|||
resultMap.zipCodeData,
|
||||
resultMap.serviceabilityDetails,
|
||||
resultMap.mobileFeePart,
|
||||
resultMap.shopQuestionInitialData?.mobileProviderNumber,
|
||||
resultMap.glassFees
|
||||
resultMap.glassFees,
|
||||
resultMap.providers
|
||||
);
|
||||
vm.$refs[SHOP_QUESTION_REF_NAME].initializeComponent(resultMap.shopQuestionInitialData);
|
||||
});
|
||||
},
|
||||
setup() {
|
||||
|
|
@ -238,7 +244,6 @@ export default {
|
|||
city: this.getServiceCityFromStore(),
|
||||
state: this.getServiceStateFromStore(),
|
||||
zipCode: this.getServiceZipCodeFromStore(),
|
||||
isVehicleProtected: this.getIsVehicleProtectedFromStore(),
|
||||
isGlassServiceableInshop: null,
|
||||
isRecalibrationServiceableInshop: null,
|
||||
isGlassServiceableMobile: null,
|
||||
|
|
@ -249,9 +254,13 @@ export default {
|
|||
mobileProviderNumber: null,
|
||||
zipContainsMilitaryBase: false,
|
||||
zipCodeCtu: null,
|
||||
SHOP_QUESTION_REF_NAME,
|
||||
mobileZipCode: '',
|
||||
mobileZipError: '',
|
||||
militaryBaseWarningExpanded: false,
|
||||
availabilityRating: null,
|
||||
RECAL_MODAL_REF_NAME,
|
||||
SITE_FOOTER_REF_NAME
|
||||
SITE_FOOTER_REF_NAME,
|
||||
errorMessages
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -264,61 +273,6 @@ export default {
|
|||
answersFromCms() {
|
||||
return this.getCmsContent('ServiceTypeQuestionWidget', 'Answers');
|
||||
},
|
||||
serviceZipCodeQuestion: {
|
||||
get() {
|
||||
return {
|
||||
state: this.state,
|
||||
zipCode: this.zipCode
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
if (newValue.zipCode !== this.zipCode) {
|
||||
this.resetMobileLocation();
|
||||
this.selectedAppointmentType = null;
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
|
||||
this.state = newValue.state;
|
||||
this.zipCode = newValue.zipCode;
|
||||
|
||||
// eslint-disable-next-line vue/valid-next-tick
|
||||
this.$nextTick();
|
||||
}
|
||||
},
|
||||
mobileLocationQuestions: {
|
||||
get() {
|
||||
return {
|
||||
addressQuestions: {
|
||||
streetAddress: this.streetAddress,
|
||||
streetAddress2: this.streetAddress2,
|
||||
city: this.city,
|
||||
state: this.state,
|
||||
zipCode: this.zipCode
|
||||
},
|
||||
isVehicleProtected: this.isVehicleProtected
|
||||
};
|
||||
},
|
||||
set(newValue) {
|
||||
this.streetAddress = newValue.addressQuestions.streetAddress;
|
||||
this.streetAddress2 = newValue.addressQuestions.streetAddress2;
|
||||
this.city = newValue.addressQuestions.city;
|
||||
this.state = newValue.addressQuestions.state;
|
||||
this.zipCode = newValue.addressQuestions.zipCode;
|
||||
this.isVehicleProtected = newValue.isVehicleProtected;
|
||||
|
||||
if (newValue.zipCode !== this.zipCode) {
|
||||
if (
|
||||
!(
|
||||
this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
)
|
||||
) {
|
||||
this.selectedAppointmentType = null;
|
||||
}
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
}
|
||||
},
|
||||
isServiceableMobile() {
|
||||
if (this.isRecalibrationServiceableMobile !== null) {
|
||||
return (
|
||||
|
|
@ -338,22 +292,14 @@ export default {
|
|||
|
||||
return this.isGlassServiceableInshop;
|
||||
},
|
||||
isShopQuestionDisplayed() {
|
||||
isInshop() {
|
||||
return (
|
||||
this.selectedAppointmentType === 'Inshop'
|
||||
|| this.selectedAppointmentType === 'Dropoff'
|
||||
);
|
||||
},
|
||||
isAppointmentTypeDisplayed() {
|
||||
return this.zipCode && !this.displayNoShopsAlert;
|
||||
},
|
||||
isMobileLocationDisplayed() {
|
||||
return (
|
||||
this.selectedAppointmentType
|
||||
=== AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType
|
||||
=== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP
|
||||
);
|
||||
isMobile() {
|
||||
return this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
},
|
||||
requiresInshopRecalibration() {
|
||||
// Specifically check for isRecalibrationServiceableMobile === false, not null or true.
|
||||
|
|
@ -375,15 +321,17 @@ export default {
|
|||
displayRecalibrationWarning() {
|
||||
return this.requiresInshopRecalibration;
|
||||
},
|
||||
displayLowAvailabilityInshop() {
|
||||
return this.availabilityRating === 'low' && this.isInshop;
|
||||
},
|
||||
displayServiceableInshopOnly() {
|
||||
return (
|
||||
!this.displayRecalibrationWarning
|
||||
&& this.isServiceableInshop
|
||||
&& !this.isServiceableMobile
|
||||
);
|
||||
return !this.isServiceableMobile && this.isServiceableInshop && !this.displayRecalibrationWarning;
|
||||
},
|
||||
displayServiceableMobileOnly() {
|
||||
return this.isServiceableMobile && !this.isServiceableInshop;
|
||||
return this.isServiceableMobile && this.recalibrationRequired && !this.isServiceableInshop;
|
||||
},
|
||||
displayMobileFeeDisclaimer() {
|
||||
return this.mainStore.isNoComp || this.mainStore.isITAC;
|
||||
},
|
||||
navigateBackScenario() {
|
||||
const { isNoComp, isITAC } = useMainStore();
|
||||
|
|
@ -393,6 +341,38 @@ export default {
|
|||
},
|
||||
isBigTruck() {
|
||||
return this.mainStore.order.vehicle.isBigTruck;
|
||||
},
|
||||
mobileZipPlaceholder() {
|
||||
return this.getCmsContent('MobileZipPlaceHolderWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
},
|
||||
militaryBaseWarningLinkText() {
|
||||
return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.HEADLINE_TEXT);
|
||||
},
|
||||
militaryBaseWarningText() {
|
||||
return this.getCmsContent('AlertMilitaryBaseZipWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||
},
|
||||
appointmentQuestionText() {
|
||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT);
|
||||
},
|
||||
scheduleRecalText() {
|
||||
if(this.requiresInshopRecalibration) {
|
||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2);
|
||||
} else {
|
||||
return this.getCmsContent('WhereWouldYouLikeServiceWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT);
|
||||
}
|
||||
},
|
||||
inShopOnlyCopy() {
|
||||
let content = this.getCmsContent('AlertInshopOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||
content = content.replace('{custom:city}', toTitleCase(this.city));
|
||||
return content;
|
||||
},
|
||||
mobileOnlyCopy() {
|
||||
let content = this.getCmsContent('AlertMobileOnlyWidget', widgetFields.ALERT_WIDGET.BODY_TEXT);
|
||||
content = content.replace('{custom:city}', toTitleCase(this.city));
|
||||
return content;
|
||||
},
|
||||
recalibrationRequired() {
|
||||
return this.mainStore.hasRecalibrationPart;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
|
@ -401,13 +381,10 @@ export default {
|
|||
useMainStore().order.serviceLocation.zipCode !== null
|
||||
);
|
||||
},
|
||||
async reloadShopData(zipCode) {
|
||||
await this.$refs[SHOP_QUESTION_REF_NAME].reloadShopData(zipCode);
|
||||
},
|
||||
async forwardButtonAction() {
|
||||
let provider = this.selectedProvider;
|
||||
this.mainStore.updateMobileFee(null);
|
||||
if (this.isMobileLocationDisplayed) {
|
||||
if (this.isMobile) {
|
||||
if (this.mainStore.isNoComp || this.mainStore.isITAC) {
|
||||
this.mainStore.updateMobileFee(this.mobileFeePart);
|
||||
}
|
||||
|
|
@ -432,7 +409,6 @@ export default {
|
|||
zipCode: this.zipCode,
|
||||
zipCodeCtu: this.zipCodeCtu,
|
||||
appointmentType: this.selectedAppointmentType,
|
||||
isVehicleProtected: this.isVehicleProtected,
|
||||
provider
|
||||
});
|
||||
|
||||
|
|
@ -466,9 +442,6 @@ export default {
|
|||
|| useMainStore().order.customer.address.zipCode
|
||||
);
|
||||
},
|
||||
getIsVehicleProtectedFromStore() {
|
||||
return useMainStore().order.serviceLocation.isVehicleProtected;
|
||||
},
|
||||
getSelectedAppointmentType() {
|
||||
return useMainStore().order.serviceLocation.appointmentType;
|
||||
},
|
||||
|
|
@ -482,12 +455,13 @@ export default {
|
|||
zipCodeData,
|
||||
serviceabilityDetails,
|
||||
mobileFeePart,
|
||||
mobileProviderNumber,
|
||||
glassFees
|
||||
glassFees,
|
||||
providers
|
||||
) {
|
||||
if (zipCodeData) {
|
||||
this.zipContainsMilitaryBase = zipCodeData.containsMilitaryBase;
|
||||
this.zipCodeCtu = zipCodeData.zipCodeCtu;
|
||||
this.city = zipCodeData.city;
|
||||
}
|
||||
|
||||
if (serviceabilityDetails) {
|
||||
|
|
@ -498,8 +472,24 @@ export default {
|
|||
this.mobileFeePart = mobileFeePart;
|
||||
}
|
||||
|
||||
if (mobileProviderNumber) {
|
||||
this.setMobileProviderNumber(mobileProviderNumber);
|
||||
if (providers) {
|
||||
this.setMobileProviderNumber(providers.mobileProviderNumber);
|
||||
let foundMatch = false;
|
||||
if(this.selectedProvider && this.selectedProvider.providerNumber) {
|
||||
const matchedProvider = providers.shopProviders.find(
|
||||
(provider) => provider.providerNumber === this.selectedProvider.providerNumber
|
||||
);
|
||||
if (matchedProvider) {
|
||||
foundMatch = true;
|
||||
this.selectedProvider = matchedProvider;
|
||||
}
|
||||
}
|
||||
if(providers.shopProviders.length > 0 && !foundMatch) {
|
||||
this.selectedProvider = providers.shopProviders[0];
|
||||
}
|
||||
else if(providers.shopProviders.length === 0) {
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (glassFees) {
|
||||
|
|
@ -521,13 +511,6 @@ export default {
|
|||
setMobileProviderNumber(providerNumber) {
|
||||
this.mobileProviderNumber = providerNumber;
|
||||
},
|
||||
resetMobileLocation() {
|
||||
this.streetAddress = '';
|
||||
this.streetAddress2 = '';
|
||||
this.city = '';
|
||||
|
||||
this.isVehicleProtected = null;
|
||||
},
|
||||
setServiceabilityDetails(serviceabilityDetails) {
|
||||
this.isGlassServiceableInshop =
|
||||
serviceabilityDetails.isGlassServiceableInshop;
|
||||
|
|
@ -537,14 +520,94 @@ export default {
|
|||
serviceabilityDetails.isGlassServiceableMobile;
|
||||
this.isRecalibrationServiceableMobile =
|
||||
serviceabilityDetails.isRecalibrationServiceableMobile;
|
||||
if (!this.isServiceableMobile) {
|
||||
this.selectedAppointmentType = AppointmentTypeStrings.IN_SHOP;
|
||||
}
|
||||
},
|
||||
async updateMobileZip() {
|
||||
this.mobileZipError = '';
|
||||
|
||||
const zipCodeData = await getMobileZipCodeData(this.mobileZipCode);
|
||||
|
||||
if (!zipCodeData.isValid) {
|
||||
this.mobileZipError = errorMessages.INVALID_ZIP;
|
||||
} else if (!zipCodeData.isServiceable) {
|
||||
this.mobileZipError = errorMessages.NO_SERVICE_IN_AREA(toTitleCase(zipCodeData.city));
|
||||
} else {
|
||||
this.city = zipCodeData.city;
|
||||
this.zipCode = this.mobileZipCode;
|
||||
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
||||
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
||||
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(this.mobileZipCode);
|
||||
serviceabilityDetailsPromise.then((result) => {
|
||||
const details = result.data;
|
||||
if (details) {
|
||||
this.setServiceabilityDetails(details);
|
||||
}
|
||||
});
|
||||
|
||||
const providersPromise = useMainStore().getProviders(this.mobileZipCode);
|
||||
providersPromise.then((result) => {
|
||||
const providers = result.data;
|
||||
if (providers) {
|
||||
this.setMobileProviderNumber(providers.mobileProviderNumber);
|
||||
if(providers.shopProviders.length > 0) {
|
||||
this.selectedProvider = providers.shopProviders[0];
|
||||
}
|
||||
else {
|
||||
this.selectedProvider = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
async handleInShopZipUpdated(newZip) {
|
||||
this.zipCode = newZip;
|
||||
const zipCodeData = await getZipCodeData(this.zipCode);
|
||||
this.city = zipCodeData.city;
|
||||
this.setCtuForMobile(zipCodeData.zipCodeCtu);
|
||||
this.setContainsMilitaryBase(zipCodeData.containsMilitaryBase);
|
||||
|
||||
const serviceabilityDetailsPromise = getServiceabilityDetails(this.zipCode);
|
||||
serviceabilityDetailsPromise.then((result) => {
|
||||
const details = result.data;
|
||||
if (details) {
|
||||
this.setServiceabilityDetails(details);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
mobileZipCode(newZip) {
|
||||
if(newZip !== '') {
|
||||
this.updateMobileZip();
|
||||
}
|
||||
},
|
||||
selectedAppointmentType() {
|
||||
this.mobileZipCode = '';
|
||||
if(this.selectedAppointmentType === AppointmentTypeStrings.IN_SHOP && this.selectedProvider) {
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 6);
|
||||
const formattedStartDate = startDate.toISOString().split('T')[0];
|
||||
const formattedEndDate = endDate.toISOString().split('T')[0];
|
||||
getAvailabilityRating(
|
||||
formattedStartDate,
|
||||
formattedEndDate,
|
||||
AppointmentTypeStrings.IN_SHOP,
|
||||
this.selectedProvider ? this.selectedProvider.providerNumber : null
|
||||
).then((rating) => {
|
||||
this.availabilityRating = rating;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
<style lang="scss" scoped>
|
||||
$page-side-padding: 1.5rem;
|
||||
|
||||
.iss-heritage-container-width {
|
||||
.service-location-container {
|
||||
position: relative;
|
||||
|
|
@ -554,58 +617,41 @@ $page-side-padding: 1.5rem;
|
|||
}
|
||||
}
|
||||
|
||||
.question-text {
|
||||
span {
|
||||
line-height: 1.5rem;
|
||||
text-align: center;
|
||||
.service-location-container {
|
||||
.subheader {
|
||||
margin: 1.25rem 0;
|
||||
}
|
||||
}
|
||||
.list-card-content p {
|
||||
&:first-of-type {
|
||||
line-height: 1.5rem;
|
||||
.form-test-error {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
&:not(:nth-of-type(1)) {
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
.choose-option {
|
||||
.button-question > div {
|
||||
&:first-of-type {
|
||||
margin-bottom: 0.95rem;
|
||||
line-height: 1.5rem;
|
||||
.appointment-type-question-text {
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 1rem;
|
||||
line-height: 1.625rem;
|
||||
flex-direction: column;
|
||||
.recal-text {
|
||||
margin-bottom: 1.25rem;
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
.button-question {
|
||||
.row.form-test-error {
|
||||
line-height: 1.5rem;
|
||||
padding-left: 0rem !important;
|
||||
}
|
||||
}
|
||||
.appointment-type-question {
|
||||
.row {
|
||||
margin-top: 0;
|
||||
.col-12 {
|
||||
margin: 0 0 .5rem 0;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
.mobile-service-zip-question {
|
||||
:deep(.form-test-error span) {
|
||||
font-weight: $font-weight-bold;
|
||||
}
|
||||
}
|
||||
.question-text {
|
||||
margin: 0;
|
||||
span {
|
||||
padding: 1rem 0;
|
||||
text-align: center;
|
||||
}
|
||||
.expandable-link-container {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
.service-location-button-question {
|
||||
.question-text {
|
||||
margin-top: 1.5rem;
|
||||
|
||||
span {
|
||||
text-align: center;
|
||||
.expandable-link {
|
||||
font-style: italic;
|
||||
font-weight: $font-weight-bold;
|
||||
text-decoration: none;
|
||||
color: $heritage-blue-primary;
|
||||
line-height: 1.375rem;
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
<script>
|
||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
||||
import modal from '@/digital-components/modal/modal.vue';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
<template>
|
||||
<textboxQuestion
|
||||
ref="zipInputTextQuestion"
|
||||
v-model="value"
|
||||
:cmsWidgetName="cmsWidgetName"
|
||||
inputId="serviceZipCode"
|
||||
questionAlignment="center"
|
||||
cornerStyle="rounded"
|
||||
mask="#####"
|
||||
:displayQuestionText="false"
|
||||
isRequired
|
||||
validationRules="zip-required|zip-format" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||
|
||||
// Supporting Files
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { required, regex } from '@/helpers/validation-rules';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
|
||||
// Define Validation Rules
|
||||
defineRule('zip-required', required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||
defineRule('zip-format', regex(/(^\d{5}$)|(^\d{5}-\d{4}$)/, errorMessages.SERVICE_ZIP_FORMAT));
|
||||
|
||||
export default {
|
||||
name: 'service-zip-question',
|
||||
components: {
|
||||
textboxQuestion
|
||||
},
|
||||
// TODO: Correct prop def.
|
||||
props: {
|
||||
modelValue: {
|
||||
serviceZipCode: String
|
||||
},
|
||||
cmsWidgetName: String
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
computed: {
|
||||
value: {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-modal-question/service-zip-question/service-zip-question.vue';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
||||
|
||||
describe('service-zip-question.vue', () => {
|
||||
it('Should get the modelValue', async () => {
|
||||
// Arrange
|
||||
const text = 'test';
|
||||
const text = '12345';
|
||||
const wrapper = shallowMount(serviceZipQuestion, {
|
||||
props: {
|
||||
modelValue: text
|
||||
|
|
@ -13,16 +13,16 @@ describe('service-zip-question.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
const modelValueText = wrapper.vm.value;
|
||||
wrapper.vm.value = 'test also';
|
||||
const modelValueText = wrapper.vm.internalZipcode;
|
||||
wrapper.vm.internalZipcode = '55555';
|
||||
|
||||
// Assert
|
||||
expect(modelValueText).toEqual('test');
|
||||
expect(modelValueText).toEqual('12345');
|
||||
});
|
||||
|
||||
it('Should emit to set value', async () => {
|
||||
// Arrange
|
||||
const text = 'test';
|
||||
const text = '12345';
|
||||
const wrapper = shallowMount(serviceZipQuestion, {
|
||||
props: {
|
||||
modelValue: text
|
||||
|
|
@ -31,9 +31,10 @@ describe('service-zip-question.vue', () => {
|
|||
});
|
||||
|
||||
// Act
|
||||
wrapper.vm.value = 'test also';
|
||||
wrapper.vm.internalZipcode = '55555';
|
||||
wrapper.vm.updateModelValue();
|
||||
|
||||
// Assert
|
||||
expect(wrapper.emitted('update:modelValue')).toEqual([['test also']]);
|
||||
expect(wrapper.emitted('update:modelValue')).toEqual([['55555']]);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
<template>
|
||||
<textboxQuestion
|
||||
ref="zipInputTextQuestion"
|
||||
v-model="internalZipcode"
|
||||
:cmsWidgetName="cmsWidgetName"
|
||||
inputId="serviceZipCode"
|
||||
cornerStyle="rounded"
|
||||
mask="#####"
|
||||
isRequired
|
||||
:hasError="hasError"
|
||||
@clickEvent="updateModelValue"
|
||||
:validationRules="`zip-required|${cmsWidgetName}-zip-format`" />
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||
|
||||
// Supporting Files
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { required, regex } from '@/helpers/validation-rules';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
|
||||
// Define Validation Rules
|
||||
defineRule('zip-required', required(errorMessages.SERVICE_ZIP_REQUIRED));
|
||||
|
||||
export default {
|
||||
name: 'service-zip-question',
|
||||
components: {
|
||||
textboxQuestion
|
||||
},
|
||||
// TODO: Correct prop def.
|
||||
props: {
|
||||
modelValue: String,
|
||||
cmsWidgetName: String,
|
||||
serviceZipFormatErrorMessage: {
|
||||
type: String,
|
||||
default: errorMessages.SERVICE_ZIP_FORMAT
|
||||
},
|
||||
hasError: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
internalZipcode: this.modelValue
|
||||
}
|
||||
},
|
||||
emits: ['update:modelValue'],
|
||||
methods: {
|
||||
updateModelValue() {
|
||||
this.$emit('update:modelValue', this.internalZipcode);
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
modelValue(newValue) {
|
||||
this.internalZipcode = newValue;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
defineRule(`${this.cmsWidgetName}-zip-format`, regex(/^\d{5}$/, this.serviceZipFormatErrorMessage));
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.textbox-question.has-success {
|
||||
:deep(input.form-control) {
|
||||
border: $border-input;
|
||||
&:focus {
|
||||
border: $border-input-focus;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
411
src/layouts/service-location/shop-address/shop-address.vue
Normal file
411
src/layouts/service-location/shop-address/shop-address.vue
Normal file
|
|
@ -0,0 +1,411 @@
|
|||
<template>
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
class="shop-address"
|
||||
aria-live="polite">
|
||||
<div class="address-header">{{ questionText }}</div>
|
||||
<div
|
||||
v-if="modelValue"
|
||||
class="current-address">
|
||||
<div class="address-line">
|
||||
<span class="shop-name">{{ displayedShopName }}</span>
|
||||
<span class="shop-distance">{{ modelValue.distanceInMiles?.toFixed(2) }} mi</span>
|
||||
</div>
|
||||
<div class="address-line">{{ getProviderAddress(modelValue) }}</div>
|
||||
<div class="address-line">
|
||||
{{ getProviderCityZipState(modelValue) }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="no-shops-found">
|
||||
{{ `No shops found within 100 miles of ${internalZipcode}` }}
|
||||
</div>
|
||||
<buttonMain
|
||||
class="more-shops-button"
|
||||
:buttonText="showMoreShopsLinkText"
|
||||
:variant="'primary'"
|
||||
@clickEvent="openModal" />
|
||||
<alert
|
||||
class="alert-shop-distance"
|
||||
v-if="modelValue?.distanceInMiles > 30"
|
||||
ref="alertShopDistance"
|
||||
cmsWidgetName="AlertShopDistanceWidget"
|
||||
alertClass="alert-warning" />
|
||||
<modal
|
||||
:ref="modalName"
|
||||
:headerText="modalHeaderText"
|
||||
:onModalOpenedCallback="onModalOpened"
|
||||
:footerButtonText="modalFooterText"
|
||||
:modalPosition="modalPositions.center"
|
||||
:allowInvalidSubmit="true"
|
||||
@footerButtonEvent="updateSelectedProvider">
|
||||
<googleMap
|
||||
id="map"
|
||||
class="mb-4"
|
||||
:markers="providerAddresses"
|
||||
:zipCode="internalZipcode" />
|
||||
<dropdownQuestion
|
||||
inputId="searchRadiusDropdown"
|
||||
ref="searchRadiusQuestion"
|
||||
v-model="searchRadiusInMiles"
|
||||
:cmsWidgetName="searchRadiusQuestionWidgetName"
|
||||
:variant="dropdownVariants.compact"
|
||||
:options="searchRadiusOptions" />
|
||||
<buttonQuestion
|
||||
ref="shopListButtonQuestion"
|
||||
v-model="internalProviderNumber"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
class="radioQuestion"
|
||||
:answers="nearbyShopsData"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start"
|
||||
isRequired
|
||||
validationRules="option-required"
|
||||
:additionalButtonData="additionalButtonData" />
|
||||
<span class="service-zip-prompt">
|
||||
{{ serviceZipPrompt }}
|
||||
</span>
|
||||
<serviceZipQuestion
|
||||
v-if="renderServiceZip"
|
||||
:ref="SERVICE_ZIP_QUESTION_REF_NAME"
|
||||
v-model="internalZipcode"
|
||||
customInputId="serviceZipCode"
|
||||
:cmsWidgetName="textboxQuestionWidgetName" />
|
||||
<div
|
||||
v-if="errorMessage"
|
||||
ref="errorMessageDiv"
|
||||
class="row my-1 form-test-error">
|
||||
<span
|
||||
class="d-inline-flex mt-0"
|
||||
role="alert">{{ errorMessage }}</span>
|
||||
</div>
|
||||
</modal>
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import modal from '@/digital-components/modal/modal.vue';
|
||||
import serviceZipQuestion from '@/layouts/service-location/service-zip-question/service-zip-question.vue';
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
||||
import dropdownQuestion from '@/digital-components/dropdown-question/dropdown-question.vue';
|
||||
import googleMap from '@/iss-components/google-map/google-map.vue';
|
||||
|
||||
// Supporting files
|
||||
import baseMixin from '@/mixins/base-mixin.js';
|
||||
import { toTitleCase } from '@/helpers/text-helper.js';
|
||||
import { markRaw } from 'vue';
|
||||
import { getAvailabilityRating } from '@/helpers/service-location-helper';
|
||||
import { useMainStore } from '@/store';
|
||||
import widgetFields from '@/constants/cms-widget-fields';
|
||||
import { dropdownVariants, modalPositions } from '@/constants/component-variants';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
|
||||
defineRule('option-required', required(errorMessages.PROVIDER_REQUIRED));
|
||||
|
||||
const SERVICE_ZIP_QUESTION_REF_NAME = 'serviceZipCodeQuestion';
|
||||
|
||||
export default {
|
||||
name: 'shop-address',
|
||||
components: {
|
||||
alert,
|
||||
buttonMain,
|
||||
modal,
|
||||
serviceZipQuestion,
|
||||
buttonQuestion,
|
||||
dropdownQuestion,
|
||||
googleMap
|
||||
},
|
||||
mixins: [baseMixin],
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => null
|
||||
},
|
||||
serviceZipcode: String,
|
||||
cmsWidgetName: String,
|
||||
validationRules: String,
|
||||
modalWidgetName: String,
|
||||
selectedAppointmentType: String,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
toTitleCase,
|
||||
serviceZipCodeTextInputId: '',
|
||||
internalZipcode: this.serviceZipcode,
|
||||
internalProviderNumber: this.modelValue?.providerNumber,
|
||||
searchRadiusQuestionWidgetName: 'SearchRadiusQuestionWidget',
|
||||
textboxQuestionWidgetName: 'ChangeLocationZipQuestionWidget',
|
||||
shopListButton: markRaw(shopListButton),
|
||||
searchRadiusInMiles: "25",
|
||||
nearbyShops: [],
|
||||
modalPositions,
|
||||
dropdownVariants,
|
||||
renderServiceZip: true,
|
||||
errorMessage: '',
|
||||
openingModal: false,
|
||||
SERVICE_ZIP_QUESTION_REF_NAME
|
||||
};
|
||||
},
|
||||
emits: ['update:modelValue', 'zip-updated'],
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, widgetFields.INPUT_QUESTION_WIDGET.QUESTION_TEXT);
|
||||
},
|
||||
showMoreShopsLinkText() {
|
||||
return this.getCmsContent('ShowMoreShopsLinkWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
},
|
||||
displayedShopName() {
|
||||
if(this.modelValue.isSafeliteShop) {
|
||||
return this.getCmsContent('SafeliteShopNameWidget', widgetFields.TEXT_BLOCK_WIDGET.TEXT);
|
||||
}
|
||||
return toTitleCase(this.modelValue.companyName);
|
||||
},
|
||||
modalHeaderText() {
|
||||
return this.getCmsContent(this.modalWidgetName, widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT).replaceAll('{custom:serviceZipcode}', this.internalZipcode);
|
||||
},
|
||||
modalFooterText() {
|
||||
return this.getCmsContent(this.modalWidgetName, widgetFields.CONTENT_GROUP_WIDGET.FOOTER_TEXT);
|
||||
},
|
||||
modalName() {
|
||||
return this.modalWidgetName;
|
||||
},
|
||||
additionalButtonData() {
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 6);
|
||||
|
||||
const formattedStartDate = startDate.toISOString().split('T')[0];
|
||||
const formattedEndDate = endDate.toISOString().split('T')[0];
|
||||
|
||||
return {
|
||||
displayAvailabilityIndicators: true,
|
||||
availabilityRatingCallback: getAvailabilityRating,
|
||||
startDate: formattedStartDate,
|
||||
endDate: formattedEndDate,
|
||||
shopAppointmentType: "InshopOrDropoff"
|
||||
};
|
||||
},
|
||||
serviceZipPrompt() {
|
||||
return this.getCmsContent(this.modalWidgetName, widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT_2);
|
||||
},
|
||||
nearbyShopsData() {
|
||||
return this.nearbyShops.map((shopProvider) => {
|
||||
const city = toTitleCase(shopProvider.address.city);
|
||||
const distanceInMiles = shopProvider.distanceInMiles.toFixed(2);
|
||||
|
||||
return {
|
||||
buttonLabel: city,
|
||||
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
||||
buttonBodyCopy: this.getFullProviderAddress(shopProvider),
|
||||
value: shopProvider.providerNumber
|
||||
};
|
||||
});
|
||||
},
|
||||
searchRadiusArray() {
|
||||
const options = this.getCmsContent(this.searchRadiusQuestionWidgetName, widgetFields.INPUT_QUESTION_WIDGET.ANSWERS);
|
||||
return options;
|
||||
},
|
||||
searchRadiusOptions() {
|
||||
const optionsObj = {};
|
||||
if(this.searchRadiusArray) {
|
||||
this.searchRadiusArray.forEach(option => {
|
||||
optionsObj[option.Name] = option.Text;
|
||||
});
|
||||
}
|
||||
return optionsObj;
|
||||
},
|
||||
providerAddresses() {
|
||||
return this.nearbyShops?.map((provider) => ({
|
||||
title: toTitleCase(provider.companyName),
|
||||
fullAddress: this.getFullProviderAddress(provider),
|
||||
addressLines: [this.getProviderAddress(provider), this.getProviderCityZipState(provider)]
|
||||
})) ?? [];
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
async internalZipcode() {
|
||||
if(this.openingModal) {
|
||||
return;
|
||||
}
|
||||
const shopsUpdated = await this.updateShops();
|
||||
if (shopsUpdated) {
|
||||
await this.$nextTick();
|
||||
this.$refs[SERVICE_ZIP_QUESTION_REF_NAME].internalZipcode = '';
|
||||
}
|
||||
},
|
||||
async searchRadiusInMiles() {
|
||||
if(this.openingModal) {
|
||||
return;
|
||||
}
|
||||
await this.updateShops();
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async updateShops(autoExpand = false) {
|
||||
this.errorMessage = '';
|
||||
let result = await this.getNearbyShops(this.searchRadiusInMiles);
|
||||
let currentSearchIndex = this.searchRadiusArray.findIndex(option => option.Name === this.searchRadiusInMiles);
|
||||
while (autoExpand && result.length === 0 && currentSearchIndex < this.searchRadiusArray.length - 1) {
|
||||
const newSearchRadius = this.searchRadiusArray[currentSearchIndex + 1].Name;
|
||||
result = await this.getNearbyShops(newSearchRadius);
|
||||
currentSearchIndex++;
|
||||
}
|
||||
if (result.length === 0) {
|
||||
this.errorMessage = errorMessages.ZIP_CODE_NOT_SERVICED_FOR_VEHICLE;
|
||||
}
|
||||
else {
|
||||
if (!result.find(shop => shop.providerNumber === this.internalProviderNumber)) {
|
||||
this.internalProviderNumber = '';
|
||||
await this.$nextTick();
|
||||
}
|
||||
this.nearbyShops = result;
|
||||
this.searchRadiusInMiles = this.searchRadiusArray[currentSearchIndex].Name;
|
||||
return true;
|
||||
}
|
||||
},
|
||||
openModal() {
|
||||
this.$refs[this.modalName].openModal();
|
||||
},
|
||||
closeModal() {
|
||||
this.$refs[this.modalName].closeModal();
|
||||
},
|
||||
onModalOpened() {
|
||||
this.openingModal = true;
|
||||
this.internalZipcode = this.serviceZipcode;
|
||||
this.searchRadiusInMiles = "25";
|
||||
this.nearbyShops = [];
|
||||
this.updateShops(true).then(() => {
|
||||
this.internalProviderNumber = this.nearbyShops[0]?.providerNumber;
|
||||
}).finally(() => {
|
||||
this.$nextTick().then(() => {
|
||||
this.openingModal = false;
|
||||
});
|
||||
});
|
||||
this.forceServiceZipRerender();
|
||||
},
|
||||
async updateSelectedProvider() {
|
||||
const selectedShop = this.nearbyShops.find(shop => shop.providerNumber === this.internalProviderNumber);
|
||||
if (selectedShop) {
|
||||
this.$emit('update:modelValue', selectedShop);
|
||||
this.$emit('zip-updated', this.internalZipcode);
|
||||
this.closeModal();
|
||||
}
|
||||
},
|
||||
async getNearbyShops(radiusInMiles) {
|
||||
const result = await useMainStore().getProviders(this.internalZipcode, radiusInMiles);
|
||||
return result.data.shopProviders;
|
||||
},
|
||||
getFullProviderAddress(provider) {
|
||||
const addressLine1 = this.getProviderAddress(provider);
|
||||
const addressLine2 = this.getProviderCityZipState(provider);
|
||||
const joinString =
|
||||
addressLine1.length > 0 && addressLine2.length > 0 ? ', ' : '';
|
||||
return [addressLine1, addressLine2].join(joinString);
|
||||
},
|
||||
getProviderAddress(provider) {
|
||||
return toTitleCase(provider?.address?.streetAddress);
|
||||
},
|
||||
getProviderCityZipState(provider) {
|
||||
const city = toTitleCase(provider?.address?.city);
|
||||
const state = provider?.address?.state ?? '';
|
||||
const zipCode = provider?.address?.zipCode ?? '';
|
||||
let addressLine2 = '';
|
||||
if (city) {
|
||||
addressLine2 += city;
|
||||
if (state || zipCode) {
|
||||
addressLine2 += state ? ', ' : ' ';
|
||||
}
|
||||
}
|
||||
if (state) {
|
||||
addressLine2 += state;
|
||||
addressLine2 += zipCode ? ' ' : '';
|
||||
}
|
||||
if (zipCode) {
|
||||
addressLine2 += zipCode;
|
||||
}
|
||||
return addressLine2;
|
||||
},
|
||||
forceServiceZipRerender() {
|
||||
this.renderServiceZip = false;
|
||||
this.$nextTick(() => {
|
||||
this.renderServiceZip = true;
|
||||
});
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import "@/styles/ux-variables-svg-strings.scss";
|
||||
.shop-address {
|
||||
.address-header {
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
margin-bottom: 0.625rem;
|
||||
}
|
||||
.address-line {
|
||||
display: flex;
|
||||
}
|
||||
.shop-distance {
|
||||
margin-left: auto;
|
||||
}
|
||||
.current-address {
|
||||
margin: .625rem 0;
|
||||
}
|
||||
.no-shops-found {
|
||||
font-size: .75rem;
|
||||
margin: .75rem 0rem;
|
||||
font-weight: $font-weight-bold;
|
||||
line-height: 1.375rem;
|
||||
}
|
||||
.more-shops-button {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
.alert-shop-distance {
|
||||
margin-top: 2.5rem;
|
||||
}
|
||||
:deep(.modal-title) {
|
||||
font-weight: 400;
|
||||
display: block;
|
||||
width: fit-content;
|
||||
}
|
||||
.radioQuestion {
|
||||
margin-bottom: .625rem;
|
||||
}
|
||||
.service-zip-prompt {
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
}
|
||||
:deep(#map) {
|
||||
height: 27rem;
|
||||
}
|
||||
:deep(.textbox-question) {
|
||||
&.has-error {
|
||||
input.form-control {
|
||||
border: $border-input;
|
||||
&:focus {
|
||||
border: $border-input-focus;
|
||||
}
|
||||
}
|
||||
}
|
||||
.form-label {
|
||||
font-weight: $font-weight-normal;
|
||||
color: $darker-gray;
|
||||
}
|
||||
.btn-primary {
|
||||
margin-bottom: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -1,294 +0,0 @@
|
|||
<template>
|
||||
<transition
|
||||
name="fade"
|
||||
mode="out-in">
|
||||
<div
|
||||
v-if="isDisplayed"
|
||||
class="shop-question"
|
||||
aria-live="polite">
|
||||
<alert
|
||||
v-if="displayDropoffInformation"
|
||||
ref="alertDropoffInformation"
|
||||
class="mb-4 drop-off-alert"
|
||||
cmsWidgetName="AlertDropoffInformationWidget"
|
||||
alertClass="alert-info"
|
||||
:isDismissible="false" />
|
||||
<buttonQuestion
|
||||
ref="buttonQuestion"
|
||||
v-model="selectedProviderNumber"
|
||||
buttonTypeString="shopListButton"
|
||||
:buttonTypeObject="shopListButton"
|
||||
class="radioQuestion"
|
||||
:questionText="questionText"
|
||||
:answers="answers"
|
||||
groupName="chooseShop"
|
||||
textPosition="text-start"
|
||||
isRequired
|
||||
validationRules="option-required"
|
||||
:additionalButtonData="additionalButtonData" />
|
||||
<textLink
|
||||
v-show="displaySeeMoreLocationsLink"
|
||||
id="showMoreShopsId"
|
||||
ref="showMoreShopsLink"
|
||||
class="show-more-shops-link"
|
||||
cmsWidgetName="ShowMoreShopsLinkWidget"
|
||||
linkType="text"
|
||||
:text="showMoreShopsLinkText"
|
||||
href="#!"
|
||||
:aria-label="showMoreShopsLinkText"
|
||||
@clickEvent="getNextShopsFromList" />
|
||||
</div>
|
||||
</transition>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// Components
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import buttonQuestion from '@/digital-components/button-question/button-question.vue';
|
||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||
|
||||
// Supporting files
|
||||
import { AppointmentTypeStrings } from '@/constants/schedule-constants.js';
|
||||
import baseMixin from '@/mixins/base-mixin.js';
|
||||
import { defineRule } from 'vee-validate';
|
||||
import { required } from '@/helpers/validation-rules';
|
||||
import errorMessages from '@/constants/error-messages';
|
||||
import { useMainStore } from '@/store/index.js';
|
||||
import { markRaw, nextTick } from 'vue';
|
||||
import { getAvailabilityRating } from '@/helpers/service-location-helper';
|
||||
import shopListButton from '@/iss-components/shop-list-button/shop-list-button.vue';
|
||||
|
||||
defineRule('option-required', required(errorMessages.OPTION_REQUIRED));
|
||||
|
||||
export default {
|
||||
name: 'shop-question',
|
||||
components: {
|
||||
alert,
|
||||
buttonQuestion,
|
||||
textLink
|
||||
},
|
||||
mixins: [baseMixin],
|
||||
props: {
|
||||
modelValue: {
|
||||
type: Object,
|
||||
default: () => null
|
||||
},
|
||||
selectedAppointmentType: String,
|
||||
cmsWidgetName: String,
|
||||
validationRules: String,
|
||||
isDisplayed: Boolean
|
||||
},
|
||||
emits: ['update:modelValue', 'updatedMobileProviderNumber'],
|
||||
data() {
|
||||
return {
|
||||
shopProviders: [],
|
||||
shopListButton: markRaw(shopListButton),
|
||||
answers: [],
|
||||
shopIndex: 0,
|
||||
displaySeeMoreLocationsLink: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
questionText() {
|
||||
return this.getCmsContent(this.cmsWidgetName, 'QuestionText');
|
||||
},
|
||||
selectedValue: {
|
||||
get() {
|
||||
return this.modelValue;
|
||||
},
|
||||
set(newValue) {
|
||||
this.$emit('update:modelValue', newValue);
|
||||
}
|
||||
},
|
||||
selectedProviderNumber: {
|
||||
get() {
|
||||
return this.selectedValue?.providerNumber;
|
||||
},
|
||||
set(newValue) {
|
||||
// Button Question only supports Number, or String data types so we must get the full object to emit
|
||||
this.selectedValue = this.getSelectedProviderObject(newValue);
|
||||
}
|
||||
},
|
||||
displayDropoffInformation() {
|
||||
return this.selectedAppointmentType === 'Dropoff';
|
||||
},
|
||||
showMoreShopsLinkText() {
|
||||
return this.getCmsContent('ShowMoreShopsLinkWidget', 'Text');
|
||||
},
|
||||
additionalButtonData() {
|
||||
const startDate = new Date();
|
||||
const endDate = new Date();
|
||||
endDate.setDate(startDate.getDate() + 6);
|
||||
|
||||
const formattedStartDate = startDate.toISOString().split('T')[0];
|
||||
const formattedEndDate = endDate.toISOString().split('T')[0];
|
||||
|
||||
return {
|
||||
displayAvailabilityIndicators: true,
|
||||
availabilityRatingCallback: getAvailabilityRating,
|
||||
startDate: formattedStartDate,
|
||||
endDate: formattedEndDate,
|
||||
shopAppointmentType: this.selectedAppointmentType
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
selectedAppointmentType: {
|
||||
async handler(newValue) {
|
||||
this.resetAnswers();
|
||||
|
||||
await nextTick();
|
||||
|
||||
this.selectedProviderNumber = null;
|
||||
|
||||
await nextTick();
|
||||
|
||||
if (newValue !== AppointmentTypeStrings.MOBILE && newValue !== AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP) {
|
||||
this.getNextShopsFromList();
|
||||
}
|
||||
}
|
||||
},
|
||||
shopProviders: {
|
||||
async handler(newValue) {
|
||||
await nextTick();
|
||||
|
||||
if (this.selectedAppointmentType) {
|
||||
const selectedShopIndex = this.getSelectedProviderIndex(
|
||||
newValue,
|
||||
this.selectedProviderNumber
|
||||
);
|
||||
|
||||
if (selectedShopIndex >= 3) {
|
||||
await this.getNextShopsFromList(selectedShopIndex + 1);
|
||||
} else {
|
||||
await this.getNextShopsFromList();
|
||||
await nextTick();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
loadInitialData(serviceZipCode) {
|
||||
return this.loadData(serviceZipCode);
|
||||
},
|
||||
loadData(serviceZipCode) {
|
||||
return useMainStore().getProviders(serviceZipCode);
|
||||
},
|
||||
initializeComponent(shopQuestionInitialData) {
|
||||
this.shopProviders = shopQuestionInitialData.shopProviders;
|
||||
},
|
||||
async getNextShopsFromList(numberToGet = 3) {
|
||||
const shopIterator = (array, n) => {
|
||||
const l = array.length;
|
||||
return () => {
|
||||
const end = this.shopIndex + n;
|
||||
const part = array.slice(this.shopIndex, end);
|
||||
this.shopIndex = end < l ? end : this.shopProviders.length;
|
||||
return part;
|
||||
};
|
||||
};
|
||||
|
||||
const toTitleCase = (str) => str.replace(/\w\S*/g, (txt) => txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase());
|
||||
|
||||
const nextShop = shopIterator(this.shopProviders, numberToGet);
|
||||
|
||||
// Map API result data
|
||||
const mappedData = nextShop().map((shopProvider) => {
|
||||
const streetAddress = toTitleCase(shopProvider.address.streetAddress);
|
||||
const city = toTitleCase(shopProvider.address.city);
|
||||
const { state } = shopProvider.address;
|
||||
const { zipCode } = shopProvider.address;
|
||||
const distanceInMiles = Math.round(shopProvider.distanceInMiles * 2) / 2;
|
||||
|
||||
return {
|
||||
buttonLabel: city,
|
||||
buttonLabelSubCopy: `${distanceInMiles} mi`,
|
||||
buttonBodyCopy: `${streetAddress}, ${city}, ${state} ${zipCode}`,
|
||||
value: shopProvider.providerNumber
|
||||
};
|
||||
});
|
||||
|
||||
if (this.answers.length === 0) {
|
||||
this.answers = mappedData;
|
||||
} else {
|
||||
mappedData.forEach((shop) => {
|
||||
this.answers.push(shop);
|
||||
});
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
if (this.shopIndex === this.shopProviders.length) {
|
||||
this.displaySeeMoreLocationsLink = false;
|
||||
} else {
|
||||
this.displaySeeMoreLocationsLink = true;
|
||||
}
|
||||
|
||||
await nextTick();
|
||||
|
||||
this.scrollToPageBottom();
|
||||
},
|
||||
resetAnswers() {
|
||||
this.answers = [];
|
||||
this.shopIndex = 0;
|
||||
},
|
||||
async reloadShopData(serviceZipCode) {
|
||||
const result = await this.loadData(serviceZipCode);
|
||||
this.initializeComponent(result.data);
|
||||
|
||||
if (result.data?.mobileProviderNumber
|
||||
&& (this.selectedAppointmentType === AppointmentTypeStrings.MOBILE
|
||||
|| this.selectedAppointmentType === AppointmentTypeStrings.MOBILE_NOT_ITAC_AND_NOT_NOCOMP)) {
|
||||
this.$emit('updatedMobileProviderNumber', result.data.mobileProviderNumber);
|
||||
}
|
||||
|
||||
this.resetAnswers();
|
||||
|
||||
await nextTick();
|
||||
await this.getNextShopsFromList();
|
||||
},
|
||||
getSelectedProviderObject(providerNumber) {
|
||||
const provider = this.shopProviders?.find((p) => p.providerNumber === providerNumber);
|
||||
return provider;
|
||||
},
|
||||
getSelectedProviderIndex(providers, selectedProviderNumber) {
|
||||
const index = providers.findIndex((p) => p.providerNumber === selectedProviderNumber);
|
||||
return index;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "@/styles/ux-variables-svg-strings.scss";
|
||||
|
||||
.shop-question {
|
||||
margin-top: 1rem;
|
||||
text-align: center;
|
||||
|
||||
.button-question {
|
||||
.question-text {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.drop-off-alert {
|
||||
background-image: url($svg-drop-off-alert);
|
||||
background-repeat: no-repeat;
|
||||
background-size: 0.75rem;
|
||||
background-position: 0.5rem 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
padding: 0.5rem 0.5rem 0.5rem 1.5rem !important;
|
||||
gap: 0.25rem;
|
||||
|
||||
.alert-heading {
|
||||
text-align: left;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -2,24 +2,20 @@
|
|||
|
||||
exports[`tpa-submit returns the initial data 1`] = `
|
||||
Object {
|
||||
"companyName": "Frederick Jones",
|
||||
"customValueMap": Object {
|
||||
"glassShop": "Frederick Jones",
|
||||
"modalPositions": Object {
|
||||
"center": "center",
|
||||
"edge": "edge",
|
||||
},
|
||||
"sections": Array [],
|
||||
"widget": Object {
|
||||
"damageLocations": "DamageLocationsWidget",
|
||||
"alertIncomplete": "AlertIncompleteWidget",
|
||||
"alertRecalWarning": "AlertRecalWarningWidget",
|
||||
"contactDetails": "ContactDetailsSectionWidget",
|
||||
"editShopLinkText": "EditShopLinkTextWidget",
|
||||
"footer": "SiteFooterWidget",
|
||||
"orderDetails": "OrderDetailsContent",
|
||||
"serviceSummary": "ServiceSummaryContent",
|
||||
"siteHeader": "SiteHeaderWidget",
|
||||
"siteSubHeader": "SiteSubHeaderWidget",
|
||||
"subheader": Object {
|
||||
"contactInfo": "ContactDetailsSubTitle",
|
||||
"damage": "DamageSubTitle",
|
||||
"shop": "PreferredShopSubTitle",
|
||||
"vehicle": "VehicleSubTitle",
|
||||
},
|
||||
},
|
||||
}
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -3,12 +3,18 @@
|
|||
exports[`contact-details-drawer snapshot matches returns the initial data 1`] = `
|
||||
Object {
|
||||
"emailAddress": "fred.tay@gmail.com",
|
||||
"extension": null,
|
||||
"firstName": "Frederick",
|
||||
"isModalOpened": false,
|
||||
"lastName": "Taylor",
|
||||
"modalPositions": Object {
|
||||
"center": "center",
|
||||
"edge": "edge",
|
||||
},
|
||||
"phoneNumber": "606-009-2943",
|
||||
"rules": Object {
|
||||
"emailAddress": "email-required|email-address-format",
|
||||
"extension": "extension-format",
|
||||
"firstName": "first-name-required",
|
||||
"lastName": "last-name-required",
|
||||
"phoneNumber": "phone-number-required|phone-number-format",
|
||||
|
|
@ -16,6 +22,7 @@ Object {
|
|||
"widget": Object {
|
||||
"drawerFooter": "ContactDetailsDrawerFooterWidget",
|
||||
"emailQuestion": "EmailQuestionWidget",
|
||||
"extensionQuestion": "ExtensionQuestionWidget",
|
||||
"firstNameQuestion": "FirstNameQuestionWidget",
|
||||
"lastNameQuestion": "LastNameQuestionWidget",
|
||||
"phoneNumberQuestion": "PhoneNumberQuestionWidget",
|
||||
|
|
|
|||
|
|
@ -65,15 +65,16 @@ describe('contact-details-drawer', () => {
|
|||
describe('method', () => {
|
||||
describe('saveContactDetails', () => {
|
||||
test.each([
|
||||
['Sarah', 'Jones', 's.jones@gmail.com', '724-996-0909'],
|
||||
[null, 'Jones', 's.jones@gmail.com', '724-996-0909'],
|
||||
['Sarah', null, 's.jones@gmail.com', '724-996-0909'],
|
||||
['Sarah', 'Jones', null, '724-996-0909'],
|
||||
['Sarah', 'Jones', 's.jones@gmail.com', null]
|
||||
['Sarah', 'Jones', 's.jones@gmail.com', '724-996-0909', '12345'],
|
||||
[null, 'Jones', 's.jones@gmail.com', '724-996-0909', '12345'],
|
||||
['Sarah', null, 's.jones@gmail.com', '724-996-0909', '12345'],
|
||||
['Sarah', 'Jones', null, '724-996-0909', '12345'],
|
||||
['Sarah', 'Jones', 's.jones@gmail.com', null, '12345'],
|
||||
['Sarah', 'Jones', 's.jones@gmail.com', '724-996-0909', null],
|
||||
|
||||
])(
|
||||
'when first name data "%p", last name "%p", email "%p", and phone number "%p", updateContactInfo called with expected',
|
||||
(firstName, lastName, emailAddress, phoneNumber) => {
|
||||
'when first name data "%p", last name "%p", email "%p", phone number "%p", and extension "%p", updateContactInfo called with expected',
|
||||
(firstName, lastName, emailAddress, phoneNumber, extension) => {
|
||||
// Arrange
|
||||
const mainInitialState = {
|
||||
order: {
|
||||
|
|
@ -81,12 +82,13 @@ describe('contact-details-drawer', () => {
|
|||
firstName: 'Frederick',
|
||||
lastName: 'Taylor',
|
||||
emailAddress: 'fred.tay@gmail.com',
|
||||
servicePhone: '606-009-2943'
|
||||
servicePhone: '606-009-2943',
|
||||
extension: '11111'
|
||||
}
|
||||
}
|
||||
};
|
||||
const initialData = {
|
||||
firstName, lastName, emailAddress, phoneNumber
|
||||
firstName, lastName, emailAddress, phoneNumber, extension
|
||||
};
|
||||
const { wrapper } = getMountedComponent(mainInitialState, initialData);
|
||||
|
||||
|
|
@ -98,7 +100,7 @@ describe('contact-details-drawer', () => {
|
|||
expect(useMainStore().updateContactInfo).toBeCalledTimes(1);
|
||||
expect(useMainStore().updateContactInfo).toBeCalledWith({ firstName, lastName, emailAddress });
|
||||
expect(useMainStore().updatePhoneNumbers).toBeCalledTimes(1);
|
||||
expect(useMainStore().updatePhoneNumbers).toBeCalledWith({ home: phoneNumber, service: phoneNumber });
|
||||
expect(useMainStore().updatePhoneNumbers).toBeCalledWith({ home: phoneNumber, service: phoneNumber, extension: extension });
|
||||
}
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
<template>
|
||||
<modal
|
||||
:ref="modalName"
|
||||
:modalPosition="modalPositions.center"
|
||||
:headerText="headerText"
|
||||
:footerButtonText="footerButtonText"
|
||||
:onModalClosedCallback="resetFormValues"
|
||||
|
|
@ -8,25 +9,27 @@
|
|||
@isModalOpened="setModalStatus"
|
||||
@footerButtonEvent="clickFooterButtonEvent">
|
||||
<template v-if="isModalOpened">
|
||||
<textboxQuestion
|
||||
ref="firstNameQuestion"
|
||||
v-model="firstName"
|
||||
inputId="firstName"
|
||||
:cmsWidgetName="widget.firstNameQuestion"
|
||||
isRequired
|
||||
:validationRules="rules.firstName" />
|
||||
<textboxQuestion
|
||||
ref="lastNameQuestion"
|
||||
v-model="lastName"
|
||||
class="mt-4"
|
||||
inputId="lastName"
|
||||
:cmsWidgetName="widget.lastNameQuestion"
|
||||
isRequired
|
||||
:validationRules="rules.lastName" />
|
||||
<div class="row">
|
||||
<textboxQuestion
|
||||
class="col"
|
||||
ref="firstNameQuestion"
|
||||
v-model="firstName"
|
||||
inputId="firstName"
|
||||
:cmsWidgetName="widget.firstNameQuestion"
|
||||
isRequired
|
||||
:validationRules="rules.firstName" />
|
||||
<textboxQuestion
|
||||
class="col"
|
||||
ref="lastNameQuestion"
|
||||
v-model="lastName"
|
||||
inputId="lastName"
|
||||
:cmsWidgetName="widget.lastNameQuestion"
|
||||
isRequired
|
||||
:validationRules="rules.lastName" />
|
||||
</div>
|
||||
<textboxQuestion
|
||||
ref="emailQuestion"
|
||||
v-model="emailAddress"
|
||||
class="mt-4"
|
||||
inputId="emailAddress"
|
||||
:cmsWidgetName="widget.emailQuestion"
|
||||
isRequired
|
||||
|
|
@ -34,13 +37,19 @@
|
|||
<textboxQuestion
|
||||
ref="phoneNumberQuestion"
|
||||
v-model="phoneNumber"
|
||||
class="mt-4"
|
||||
inputId="phoneNumber"
|
||||
:cmsWidgetName="widget.phoneNumberQuestion"
|
||||
isRequired
|
||||
:mask="phoneMask"
|
||||
disableAutoFill
|
||||
:validationRules="rules.phoneNumber" />
|
||||
<textboxQuestion
|
||||
ref="extensionQuestion"
|
||||
v-model="extension"
|
||||
inputId="extension"
|
||||
:cmsWidgetName="widget.extensionQuestion"
|
||||
disableAutoFill
|
||||
:validationRules="rules.extension" />
|
||||
</template>
|
||||
</modal>
|
||||
</template>
|
||||
|
|
@ -51,10 +60,11 @@ import modal from '@/digital-components/modal/modal.vue';
|
|||
import textboxQuestion from '@/digital-components/textbox-question/textbox-question.vue';
|
||||
|
||||
// Supporting Files
|
||||
import { useMainStore } from '@/store/index.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import globalRules from '@/constants/global-rules.js';
|
||||
import MaskaFormattedMasks from '@/constants/maska-masks';
|
||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||
import { modalPositions } from '@/constants/component-variants';
|
||||
|
||||
export default {
|
||||
name: 'contact-details-drawer',
|
||||
|
|
@ -67,27 +77,32 @@ export default {
|
|||
const { firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
servicePhone } = useMainStore().contactInfo;
|
||||
servicePhone,
|
||||
extension } = useMainStore().contactInfo;
|
||||
return {
|
||||
isModalOpened: false,
|
||||
firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
phoneNumber: servicePhone,
|
||||
extension: extension,
|
||||
widget: {
|
||||
title: 'ContactDetailsDrawerHeaderWidget',
|
||||
firstNameQuestion: 'FirstNameQuestionWidget',
|
||||
lastNameQuestion: 'LastNameQuestionWidget',
|
||||
emailQuestion: 'EmailQuestionWidget',
|
||||
phoneNumberQuestion: 'PhoneNumberQuestionWidget',
|
||||
extensionQuestion: 'ExtensionQuestionWidget',
|
||||
drawerFooter: 'ContactDetailsDrawerFooterWidget'
|
||||
},
|
||||
rules: {
|
||||
firstName: globalRules.FIRST_NAME_REQUIRED,
|
||||
lastName: globalRules.LAST_NAME_REQUIRED,
|
||||
emailAddress: `${globalRules.EMAIL_ADDRESS_REQUIRED}|${globalRules.EMAIL_ADDRESS_FORMAT}`,
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`
|
||||
}
|
||||
phoneNumber: `${globalRules.PHONE_NUMBER_REQUIRED}|${globalRules.PHONE_NUMBER_FORMAT}`,
|
||||
extension: `${globalRules.EXTENSION_FORMAT}`
|
||||
},
|
||||
modalPositions
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -121,10 +136,11 @@ export default {
|
|||
lastName: this.lastName,
|
||||
emailAddress: this.emailAddress
|
||||
};
|
||||
useMainStore().updateContactInfo(contactInfo);
|
||||
useMainStore().updatePhoneNumbers({
|
||||
this.mainStore.updateContactInfo(contactInfo);
|
||||
this.mainStore.updatePhoneNumbers({
|
||||
home: this.phoneNumber,
|
||||
service: this.phoneNumber
|
||||
service: this.phoneNumber,
|
||||
extension: this.extension
|
||||
});
|
||||
this.$emit('update-contact-details');
|
||||
},
|
||||
|
|
@ -132,11 +148,13 @@ export default {
|
|||
const { firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
servicePhone } = useMainStore().contactInfo;
|
||||
servicePhone,
|
||||
extension } = this.mainStore.contactInfo;
|
||||
this.firstName = firstName;
|
||||
this.lastName = lastName;
|
||||
this.emailAddress = emailAddress;
|
||||
this.phoneNumber = servicePhone;
|
||||
this.extension = extension;
|
||||
},
|
||||
openModal() {
|
||||
this.modal.openModal();
|
||||
|
|
@ -155,5 +173,14 @@ export default {
|
|||
font-size: $h5-font-size;
|
||||
font-weight: $font-weight-normal !important;
|
||||
}
|
||||
.textbox-question {
|
||||
margin-bottom: 1.25rem;
|
||||
:deep(label:has(b)) {
|
||||
font-weight: $font-weight-normal;
|
||||
b {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ describe('deductible-box', () => {
|
|||
|
||||
it('renders the correct deductible label', () => {
|
||||
const labelElement = wrapper.find('#deductibleLabel');
|
||||
expect(labelElement.text()).toBe('Deductible');
|
||||
expect(labelElement.text()).toBe('Deductible:');
|
||||
});
|
||||
|
||||
it('has the correct id', () => {
|
||||
|
|
@ -26,12 +26,8 @@ describe('deductible-box', () => {
|
|||
});
|
||||
|
||||
it('has the correct classes', () => {
|
||||
expect(wrapper.classes().length).toBe(5);
|
||||
expect(wrapper.classes().length).toBe(1);
|
||||
expect(wrapper.classes()).toContain('deductible-box');
|
||||
expect(wrapper.classes()).toContain('d-flex');
|
||||
expect(wrapper.classes()).toContain('justify-content-between');
|
||||
expect(wrapper.classes()).toContain('align-items-center');
|
||||
expect(wrapper.classes()).toContain('py-2');
|
||||
});
|
||||
it.each([
|
||||
['', ''],
|
||||
|
|
|
|||
|
|
@ -1,17 +1,9 @@
|
|||
<template>
|
||||
<div
|
||||
id="deductibleBox"
|
||||
class="deductible-box d-flex justify-content-between align-items-center py-2">
|
||||
<p
|
||||
id="deductibleLabel"
|
||||
class="deductible-box__text">
|
||||
Deductible
|
||||
</p>
|
||||
<p
|
||||
id="deductibleValue"
|
||||
class="deductible-box__text">
|
||||
{{ value }}
|
||||
</p>
|
||||
class="deductible-box">
|
||||
<span id="deductibleLabel" class="deductible-label">Deductible:</span>
|
||||
<span id="deductibleValue" class="deductible-value">{{ value }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -28,12 +20,17 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
.deductible-box {
|
||||
background-color: $green;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: .25rem;
|
||||
}
|
||||
|
||||
.deductible-box__text {
|
||||
color: white;
|
||||
.deductible-label {
|
||||
color: $black;
|
||||
font-weight: 600;
|
||||
}
|
||||
.deductible-value {
|
||||
color: $green;
|
||||
font-weight: 500;
|
||||
margin: 0;
|
||||
font-size: 1.625rem;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@ describe('ReviewBlock.vue', () => {
|
|||
});
|
||||
|
||||
it('renders the correct number of lines', () => {
|
||||
const lineElements = wrapper.findAll('.review-block__body--line');
|
||||
const lineElements = wrapper.findAll('.review-body p');
|
||||
expect(lineElements.length).toBe(lines.length);
|
||||
});
|
||||
|
||||
it('renders the correct line text', () => {
|
||||
const lineElements = wrapper.findAll('.review-block__body--line');
|
||||
const lineElements = wrapper.findAll('.review-body p');
|
||||
lines.forEach((line, index) => {
|
||||
expect(lineElements.at(index).text()).toBe(line);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,29 +1,28 @@
|
|||
<template>
|
||||
<div class="review-block">
|
||||
<div class="d-flex justify-content-between">
|
||||
<p class="review-block__header small-strong pb-1">
|
||||
{{ customHeaderText }}
|
||||
</p>
|
||||
<textLink
|
||||
linkType="textSmall"
|
||||
:text="editLinkText"
|
||||
useLoadingModal
|
||||
href="javascript:void(0)"
|
||||
class="link"
|
||||
@clickEvent="editClicked">
|
||||
<template
|
||||
v-if="editScreenReaderTextCmsWidgetName"
|
||||
#after-text>
|
||||
<span class="sr-only"> {{ screenReaderOnlyText }} </span>
|
||||
</template>
|
||||
</textLink>
|
||||
</div>
|
||||
<p
|
||||
v-for="line in lines"
|
||||
:key="line"
|
||||
class="small review-block__body--line"
|
||||
v-html="line">
|
||||
<p class="review-block__header">
|
||||
{{ customHeaderText }}
|
||||
</p>
|
||||
<div class="review-body">
|
||||
<p
|
||||
v-for="line in lines"
|
||||
:key="line"
|
||||
v-html="line">
|
||||
</p>
|
||||
</div>
|
||||
<textLink
|
||||
linkType="text"
|
||||
:text="editLinkText"
|
||||
useLoadingModal
|
||||
href="javascript:void(0)"
|
||||
class="link"
|
||||
@clickEvent="editClicked">
|
||||
<template
|
||||
v-if="editScreenReaderTextCmsWidgetName"
|
||||
#after-text>
|
||||
<span class="sr-only"> {{ screenReaderOnlyText }} </span>
|
||||
</template>
|
||||
</textLink>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -36,14 +35,13 @@ export default {
|
|||
props: {
|
||||
customHeaderText: String,
|
||||
editScreenReaderTextCmsWidgetName: String,
|
||||
lines: Array
|
||||
lines: Array,
|
||||
editLinkText: {
|
||||
type: String,
|
||||
default: 'Edit'
|
||||
},
|
||||
},
|
||||
emits: ['click-edit'],
|
||||
data() {
|
||||
return {
|
||||
editLinkText: 'Edit'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
editClicked() {
|
||||
this.$emit('click-edit');
|
||||
|
|
@ -59,12 +57,16 @@ export default {
|
|||
}
|
||||
.review-block__header {
|
||||
color: $black;
|
||||
font-weight: $font-weight-bold;
|
||||
margin-bottom: .625rem;
|
||||
}
|
||||
.review-block__body--line {
|
||||
color: $gray-600;
|
||||
|
||||
.review-body {
|
||||
margin-bottom: .625rem
|
||||
}
|
||||
|
||||
.link {
|
||||
text-underline-offset: 1px;
|
||||
font-weight: $font-weight-normal
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,15 @@ import coverageStatuses from '@/constants/coverage-statuses';
|
|||
jest.mock('@/helpers/cms-content-helper', () => ({
|
||||
fetchCmsContentForPage: jest.fn(),
|
||||
doesCopyContainRouterLink: jest.fn(),
|
||||
getStringWithCustomValues: jest.fn(),
|
||||
getStringWithCustomValues: jest.fn((str, customValueMap) => {
|
||||
let newString = str ?? '';
|
||||
if (customValueMap != null) {
|
||||
Object.keys(customValueMap).forEach((key) => {
|
||||
newString = newString.replaceAll(`{custom:${key}}`, customValueMap[key]);
|
||||
});
|
||||
}
|
||||
return newString;
|
||||
}),
|
||||
processIfStatements: jest.fn()
|
||||
}));
|
||||
|
||||
|
|
@ -129,11 +137,7 @@ describe('tpa-submit', () => {
|
|||
|
||||
// Assert
|
||||
expect(subHeader.exists()).toBeTruthy();
|
||||
expect(subHeader.props().justifyText).toBe('center');
|
||||
expect(subHeader.props().marginTopSizeOverride).toBe(4);
|
||||
expect(subHeader.classes()).toContain('text-color--black');
|
||||
expect(subHeader.classes()).toContain('fs-5');
|
||||
expect(subHeader.classes()).toContain('tpa-submit__title--line-height');
|
||||
expect(subHeader.classes()).toContain('tpa-submit-title');
|
||||
});
|
||||
test('sub header body one', () => {
|
||||
// Arrange
|
||||
|
|
@ -144,34 +148,6 @@ describe('tpa-submit', () => {
|
|||
|
||||
// Assert
|
||||
expect(subHeaderBodyOne.exists()).toBeTruthy();
|
||||
expect(subHeaderBodyOne.classes()).toContain('small');
|
||||
expect(subHeaderBodyOne.classes()).toContain('text-color--darker-gray');
|
||||
});
|
||||
test('sub header body two', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(tpaSubmit, getMountOptions());
|
||||
|
||||
// Act
|
||||
const subHeaderBodyTwo = wrapper.findComponent({ ref: 'tpaSubmitSubHeaderBodyTwo' });
|
||||
|
||||
// Assert
|
||||
expect(subHeaderBodyTwo.exists()).toBeTruthy();
|
||||
expect(subHeaderBodyTwo.classes()).toContain('mb-4');
|
||||
expect(subHeaderBodyTwo.classes()).toContain('small');
|
||||
expect(subHeaderBodyTwo.classes()).toContain('text-color--darker-gray');
|
||||
});
|
||||
test('main button one', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(tpaSubmit, getMountOptions());
|
||||
|
||||
// Act
|
||||
const mainButton = wrapper.findComponent({ ref: 'buttonMainOne' });
|
||||
|
||||
// Assert
|
||||
expect(mainButton.exists()).toBeTruthy();
|
||||
expect(mainButton.props().variant).toBe('success');
|
||||
expect(mainButton.classes()).toContain('w-100');
|
||||
expect(mainButton.classes()).toContain('mb-5');
|
||||
});
|
||||
test('service summary section', () => {
|
||||
// Arrange
|
||||
|
|
@ -183,21 +159,6 @@ describe('tpa-submit', () => {
|
|||
// Assert
|
||||
expect(serviceSummarySection.exists()).toBeTruthy();
|
||||
});
|
||||
test('service summary title', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(tpaSubmit, getMountOptions());
|
||||
|
||||
// Act
|
||||
const serviceSummaryTitle = wrapper.findComponent({ ref: 'tpaSubmitServiceSummaryTitle' });
|
||||
|
||||
// Assert
|
||||
expect(serviceSummaryTitle.exists()).toBeTruthy();
|
||||
expect(serviceSummaryTitle.props().marginTopSizeOverride).toBe(4);
|
||||
expect(serviceSummaryTitle.classes()).toContain('fw-bold');
|
||||
expect(serviceSummaryTitle.classes()).toContain('fs-1');
|
||||
expect(serviceSummaryTitle.classes()).toContain('lh-lg');
|
||||
expect(serviceSummaryTitle.classes()).toContain('text-color--black');
|
||||
});
|
||||
describe('review blocks', () => {
|
||||
const title1 = 'Section 1';
|
||||
const title2 = 'Another Section';
|
||||
|
|
@ -253,24 +214,8 @@ describe('tpa-submit', () => {
|
|||
|
||||
// Assert
|
||||
expect(submitOrderDetailsTitle.exists()).toBeTruthy();
|
||||
expect(submitOrderDetailsTitle.props().marginTopSizeOverride).toBe(4);
|
||||
expect(submitOrderDetailsTitle.classes()).toContain('fw-bold');
|
||||
expect(submitOrderDetailsTitle.classes()).toContain('text-color--black');
|
||||
});
|
||||
test('submit order details body', () => {
|
||||
// Arrange
|
||||
const wrapper = shallowMount(tpaSubmit, getMountOptions());
|
||||
|
||||
// Act
|
||||
const submitOrderDetailsTitle = wrapper.findComponent({ ref: 'tpaSubmitOrderDetailsBody' });
|
||||
|
||||
// Assert
|
||||
expect(submitOrderDetailsTitle.exists()).toBeTruthy();
|
||||
expect(submitOrderDetailsTitle.props().marginTopSizeOverride).toBe(4);
|
||||
expect(submitOrderDetailsTitle.classes()).toContain('mb-4');
|
||||
expect(submitOrderDetailsTitle.classes()).toContain('px-4');
|
||||
expect(submitOrderDetailsTitle.classes()).toContain('small');
|
||||
expect(submitOrderDetailsTitle.classes()).toContain('text-color--darker-gray');
|
||||
expect(submitOrderDetailsTitle.classes()).toContain('order-details-title');
|
||||
});
|
||||
test('deductible box', () => {
|
||||
// Arrange
|
||||
|
|
@ -306,7 +251,7 @@ describe('tpa-submit', () => {
|
|||
});
|
||||
});
|
||||
describe('before route enter', () => {
|
||||
test('produces 4 sections', async () => {
|
||||
test('produces 2 sections', async () => {
|
||||
// Arrange
|
||||
const { wrapper } = getMountedComponent();
|
||||
expect(wrapper.vm.sections.length).toBe(0);
|
||||
|
|
@ -320,65 +265,13 @@ describe('tpa-submit', () => {
|
|||
);
|
||||
|
||||
// Assert
|
||||
expect(wrapper.vm.sections.length).toBe(4);
|
||||
});
|
||||
test.each([
|
||||
['2004', 'Honda', 'Civic', '2004 Honda Civic'],
|
||||
[null, 'Honda', 'Civic', 'Honda Civic'],
|
||||
['2004', '', 'Civic', '2004 Civic'],
|
||||
['2004', 'Honda', null, '2004 Honda'],
|
||||
['2004', null, undefined, '2004'],
|
||||
[null, null, null, '']
|
||||
])(
|
||||
'when store vehicle has year %p, make %p, and model %p, has line %p',
|
||||
async (year, make, model, line) => {
|
||||
// Arrange
|
||||
const initialStore = {
|
||||
order: {
|
||||
vehicle: { year, make, model }
|
||||
}
|
||||
};
|
||||
const { wrapper } = getMountedComponent(initialStore);
|
||||
const vehicleSectionIndex = 0;
|
||||
const expectedLines = [line];
|
||||
|
||||
// Act
|
||||
await tpaSubmit.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { issPage: 'tpa-submit' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
|
||||
// Assert
|
||||
const vehicleSection = wrapper.vm.sections[vehicleSectionIndex];
|
||||
expect(vehicleSection.lines).toStrictEqual(expectedLines);
|
||||
}
|
||||
);
|
||||
test('damage section lines equal result from getDamageDisplayContent', async () => {
|
||||
// Arrange
|
||||
const { wrapper } = getMountedComponent();
|
||||
const damageSectionIndex = 1;
|
||||
const expectedLines = ['hi', 'potato', 'vehicle 3'];
|
||||
getDamageDisplayContent.mockImplementationOnce(() => expectedLines);
|
||||
|
||||
// Act
|
||||
await tpaSubmit.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { issPage: 'tpa-submit' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
|
||||
// Assert
|
||||
const damageSection = wrapper.vm.sections[damageSectionIndex];
|
||||
expect(damageSection.lines).toEqual(expectedLines);
|
||||
expect(wrapper.vm.sections.length).toBe(2);
|
||||
});
|
||||
describe('preferred shop section', () => {
|
||||
test('has three lines', async () => {
|
||||
test('has two lines', async () => {
|
||||
// Arrange
|
||||
const { wrapper } = getMountedComponent();
|
||||
const preferredShopSectionIndex = 2;
|
||||
const preferredShopSectionIndex = 0;
|
||||
|
||||
// Act
|
||||
await tpaSubmit.beforeRouteEnter.call(
|
||||
|
|
@ -390,15 +283,15 @@ describe('tpa-submit', () => {
|
|||
|
||||
// Assert
|
||||
const preferredShopSection = wrapper.vm.sections[preferredShopSectionIndex];
|
||||
expect(preferredShopSection.lines.length).toBe(3);
|
||||
expect(preferredShopSection.lines.length).toBe(2);
|
||||
});
|
||||
test('first line is value returned from toTitleCase method', async () => {
|
||||
test('title is value returned from toTitleCase method', async () => {
|
||||
// Arrange
|
||||
const initialData = { companyName: 'some value' };
|
||||
const { wrapper } = getMountedComponent({}, initialData);
|
||||
const expectedName = 'some expected name';
|
||||
toTitleCase.mockImplementationOnce(() => expectedName);
|
||||
const preferredShopSectionIndex = 2;
|
||||
const preferredShopSectionIndex = 0;
|
||||
|
||||
// Act
|
||||
await tpaSubmit.beforeRouteEnter.call(
|
||||
|
|
@ -410,9 +303,9 @@ describe('tpa-submit', () => {
|
|||
|
||||
// Assert
|
||||
const preferredShopSection = wrapper.vm.sections[preferredShopSectionIndex];
|
||||
expect(preferredShopSection.lines[0]).toBe(expectedName);
|
||||
expect(preferredShopSection.title).toBe(expectedName);
|
||||
});
|
||||
test('second line is expected and formatAddress called', async () => {
|
||||
test('first line is expected and formatAddress called', async () => {
|
||||
// Arrange
|
||||
const address = {
|
||||
streetAddress: '123 South Ln',
|
||||
|
|
@ -430,7 +323,7 @@ describe('tpa-submit', () => {
|
|||
const { wrapper } = getMountedComponent(initialStore);
|
||||
const line = 'some returned line';
|
||||
formatAddress.mockImplementationOnce(() => line);
|
||||
const preferredShopSectionIndex = 2;
|
||||
const preferredShopSectionIndex = 0;
|
||||
|
||||
// Act
|
||||
await tpaSubmit.beforeRouteEnter.call(
|
||||
|
|
@ -442,7 +335,7 @@ describe('tpa-submit', () => {
|
|||
|
||||
// Assert
|
||||
const preferredShopSection = wrapper.vm.sections[preferredShopSectionIndex];
|
||||
expect(preferredShopSection.lines[1]).toBe(line);
|
||||
expect(preferredShopSection.lines[0]).toBe(line);
|
||||
expect(formatAddress).toHaveBeenCalledTimes(1);
|
||||
expect(formatAddress).toHaveBeenCalledWith(
|
||||
address.streetAddress,
|
||||
|
|
@ -452,7 +345,7 @@ describe('tpa-submit', () => {
|
|||
address.zipCode
|
||||
);
|
||||
});
|
||||
test('third line is expected and toDisplayPhoneNumber called', async () => {
|
||||
test('second line is expected and toDisplayPhoneNumber called', async () => {
|
||||
// Arrange
|
||||
const phoneNumber = '9998887777';
|
||||
const initialStore = {
|
||||
|
|
@ -465,7 +358,7 @@ describe('tpa-submit', () => {
|
|||
const { wrapper } = getMountedComponent(initialStore);
|
||||
const expectedLine = 'returned from to display phone num';
|
||||
toDisplayPhoneNumber.mockImplementationOnce(() => expectedLine);
|
||||
const preferredShopSectionIndex = 2;
|
||||
const preferredShopSectionIndex = 0;
|
||||
|
||||
// Act
|
||||
await tpaSubmit.beforeRouteEnter.call(
|
||||
|
|
@ -477,7 +370,7 @@ describe('tpa-submit', () => {
|
|||
|
||||
// Assert
|
||||
const preferredShopSection = wrapper.vm.sections[preferredShopSectionIndex];
|
||||
expect(preferredShopSection.lines[2]).toBe(expectedLine);
|
||||
expect(preferredShopSection.lines[1]).toBe(expectedLine);
|
||||
expect(toDisplayPhoneNumber).toHaveBeenCalledWith(phoneNumber);
|
||||
});
|
||||
});
|
||||
|
|
@ -487,8 +380,14 @@ describe('tpa-submit', () => {
|
|||
const lastName = 'Eddison';
|
||||
const emailAddress = 'myname@gmail.com';
|
||||
const servicePhone = '0001112222';
|
||||
const providerCompanyName = 'Some Provider LLC';
|
||||
const initialStore = {
|
||||
order: {
|
||||
serviceLocation: {
|
||||
provider: {
|
||||
companyName: providerCompanyName
|
||||
}
|
||||
},
|
||||
contactInfo: {
|
||||
firstName,
|
||||
lastName,
|
||||
|
|
@ -498,11 +397,11 @@ describe('tpa-submit', () => {
|
|||
}
|
||||
};
|
||||
const { wrapper } = getMountedComponent(initialStore);
|
||||
const expectedLine1 = 'Jones Eddison';
|
||||
const expectedLine2 = emailAddress;
|
||||
const expectedLine3 = 'some value returned';
|
||||
toDisplayPhoneNumber.mockImplementation((number) => (number === servicePhone ? expectedLine3 : ''));
|
||||
const contactInfoSectionIndex = 3;
|
||||
const expectedEmail = emailAddress;
|
||||
const expectedPhone = 'some value returned';
|
||||
toDisplayPhoneNumber.mockImplementation((number) => (number === servicePhone ? expectedPhone : ''));
|
||||
const contactInfoSectionIndex = 1;
|
||||
wrapper.vm.getCmsContent.mockImplementation(() => '{custom:contactPhone} or {custom:contactEmail}');
|
||||
|
||||
// Act
|
||||
await tpaSubmit.beforeRouteEnter.call(
|
||||
|
|
@ -511,12 +410,59 @@ describe('tpa-submit', () => {
|
|||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
wrapper.vm.setSections();
|
||||
|
||||
// Assert
|
||||
const contactInfoSection = wrapper.vm.sections[contactInfoSectionIndex];
|
||||
expect(contactInfoSection.lines[0]).toBe(expectedLine1);
|
||||
expect(contactInfoSection.lines[1]).toBe(expectedLine2);
|
||||
expect(contactInfoSection.lines[2]).toBe(expectedLine3);
|
||||
expect(contactInfoSection.lines[0]).toContain(expectedEmail);
|
||||
expect(contactInfoSection.lines[0]).toContain(expectedPhone);
|
||||
expect(toDisplayPhoneNumber).toHaveBeenCalledWith(servicePhone);
|
||||
});
|
||||
test('contact info section has expected content with extension', async () => {
|
||||
// Arrange
|
||||
const firstName = 'Jones';
|
||||
const lastName = 'Eddison';
|
||||
const emailAddress = 'myname@gmail.com';
|
||||
const servicePhone = '0001112222';
|
||||
const extension = '12345';
|
||||
const providerCompanyName = 'Some Provider LLC';
|
||||
const initialStore = {
|
||||
order: {
|
||||
serviceLocation: {
|
||||
provider: {
|
||||
companyName: providerCompanyName
|
||||
}
|
||||
},
|
||||
contactInfo: {
|
||||
firstName,
|
||||
lastName,
|
||||
emailAddress,
|
||||
servicePhone,
|
||||
extension
|
||||
}
|
||||
}
|
||||
};
|
||||
const { wrapper } = getMountedComponent(initialStore);
|
||||
const expectedEmail = emailAddress;
|
||||
const expectedPhone = 'some value returned';
|
||||
toDisplayPhoneNumber.mockImplementation((number) => (number === servicePhone ? expectedPhone : ''));
|
||||
const contactInfoSectionIndex = 1;
|
||||
wrapper.vm.getCmsContent.mockImplementation(() => '{custom:contactPhone} or {custom:contactEmail}');
|
||||
|
||||
// Act
|
||||
await tpaSubmit.beforeRouteEnter.call(
|
||||
wrapper.vm,
|
||||
{ query: { issPage: 'tpa-submit' } },
|
||||
undefined,
|
||||
(c) => c(wrapper.vm)
|
||||
);
|
||||
wrapper.vm.setSections();
|
||||
|
||||
// Assert
|
||||
const contactInfoSection = wrapper.vm.sections[contactInfoSectionIndex];
|
||||
expect(contactInfoSection.lines[0]).toContain(expectedEmail);
|
||||
expect(contactInfoSection.lines[0]).toContain(expectedPhone);
|
||||
expect(contactInfoSection.lines[0]).toContain(`Ext. ${extension}`);
|
||||
expect(toDisplayPhoneNumber).toHaveBeenCalledWith(servicePhone);
|
||||
});
|
||||
});
|
||||
|
|
@ -524,7 +470,6 @@ describe('tpa-submit', () => {
|
|||
test.each([
|
||||
['subHeaderTitle', 'SiteSubHeaderWidget', widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT, 'site sub header'],
|
||||
['subHeaderBodyOne', 'SiteSubHeaderWidget', widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT, 'sub header body one'],
|
||||
['serviceSummaryText', 'ServiceSummaryContent', widgetFields.TEXT_BLOCK_WIDGET.TEXT, 'service summary text'],
|
||||
['orderDetailsTitle', 'OrderDetailsContent', widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT, 'order details title'],
|
||||
['forwardButtonText', 'SiteFooterWidget', widgetFields.FOOTER_WIDGET.FORWARD_BUTTON_TEXT, 'forward button text']
|
||||
])('computed %p returns expected value', (computedName, widgetLabel, fieldLabel, expected) => {
|
||||
|
|
|
|||
|
|
@ -13,53 +13,52 @@
|
|||
</div>
|
||||
<div class="iss-heritage-container-width">
|
||||
<div class="tpa-submit-container iss-heritage-content-container-width">
|
||||
<!-- TODO fix styling -->
|
||||
<alert
|
||||
ref="alertIncomplete"
|
||||
alertClass="alert-warning"
|
||||
:cmsWidgetName="widget.alertIncomplete"
|
||||
/>
|
||||
<textBlock
|
||||
ref="subHeaderTitle"
|
||||
:customText="subHeaderTitle"
|
||||
justifyText="center"
|
||||
:marginTopSizeOverride="4"
|
||||
class="text-color--black fs-5 tpa-submit__title--line-height" />
|
||||
class="tpa-submit-title"/>
|
||||
<textBlock
|
||||
id="tpaSubmitSubHeaderBodyOne"
|
||||
ref="tpaSubmitSubHeaderBodyOne"
|
||||
:customText="subHeaderBodyOne"
|
||||
class="small text-color--darker-gray" />
|
||||
<textBlock
|
||||
id="tpaSubmitSubHeaderBodyTwo"
|
||||
ref="tpaSubmitSubHeaderBodyTwo"
|
||||
:customText="subHeaderBodyTwo"
|
||||
class="mb-4 small text-color--darker-gray" />
|
||||
<buttonMain
|
||||
ref="buttonMainOne"
|
||||
variant="success"
|
||||
:buttonText="forwardButtonText"
|
||||
class="w-100 mb-5"
|
||||
@clickEvent="forwardButtonAction" />
|
||||
<hr class="mb-0" />
|
||||
:customText="subHeaderBodyOne" />
|
||||
<alert
|
||||
v-if="recalibrationRequired"
|
||||
ref="alertRecalWarning"
|
||||
alertClass="alert-warning recal-alert"
|
||||
:isCollapsible="true"
|
||||
:cmsWidgetName="widget.alertRecalWarning"
|
||||
@textLinkClicked="openRecalModal" />
|
||||
<modal
|
||||
ref="recalModal"
|
||||
class="recal-modal"
|
||||
:modalPosition="modalPositions.center"
|
||||
:headerText="recalModalContent.headerText"
|
||||
:footerButtonText="recalModalContent.footerButtonText"
|
||||
@footerButtonEvent="closeRecalModal">
|
||||
<div class="recal-modal-subheader">{{ recalModalContent.subHeaderText }}</div>
|
||||
<img class="recal-modal-image" :src="recalModalContent.image" />
|
||||
<div class="recal-modal-body" v-html="recalModalContent.bodyText"></div>
|
||||
</modal>
|
||||
<hr />
|
||||
<div id="serviceSummarySection">
|
||||
<textBlock
|
||||
id="tpaSubmitServiceSummaryTitle"
|
||||
ref="tpaSubmitServiceSummaryTitle"
|
||||
:customText="serviceSummaryText"
|
||||
:marginTopSizeOverride="4"
|
||||
class="fw-bold fs-1 lh-lg text-color--black" />
|
||||
<div class="px-4 my-3">
|
||||
<div
|
||||
v-for="(section, index) in sections"
|
||||
:key="section.title">
|
||||
<hr
|
||||
v-if="index !== 0"
|
||||
class="my-3" />
|
||||
<reviewBlock
|
||||
:id="'review-block-' + index"
|
||||
:customHeaderText="section.title"
|
||||
:lines="section.lines"
|
||||
@clickEdit="() => section.onClickEdit()" />
|
||||
</div>
|
||||
<div
|
||||
v-for="(section, index) in sections"
|
||||
:key="section.title">
|
||||
<hr v-if="index !== 0" />
|
||||
<reviewBlock
|
||||
:id="'review-block-' + index"
|
||||
:customHeaderText="section.title"
|
||||
:lines="section.lines"
|
||||
:editLinkText="section.editLinkText"
|
||||
@clickEdit="() => section.onClickEdit()" />
|
||||
</div>
|
||||
</div>
|
||||
<hr class="mb-0" />
|
||||
<hr />
|
||||
<div
|
||||
id="submitOrderDetailsSection"
|
||||
ref="submitOrderDetailsSection">
|
||||
|
|
@ -67,17 +66,10 @@
|
|||
id="tpaSubmitOrderDetailsTitle"
|
||||
ref="tpaSubmitOrderDetailsTitle"
|
||||
:customText="orderDetailsTitle"
|
||||
:marginTopSizeOverride="4"
|
||||
class="fw-bold text-color--black" />
|
||||
<textBlock
|
||||
id="tpaSubmitOrderDetailsBody"
|
||||
ref="tpaSubmitOrderDetailsBody"
|
||||
:customText="orderDetailsBody"
|
||||
:marginTopSizeOverride="4"
|
||||
class="mb-4 px-4 small text-color--darker-gray" />
|
||||
:marginTopSizeOverride="0"
|
||||
class="fw-bold order-details-title" />
|
||||
<deductibleBox
|
||||
ref="deductibleBox"
|
||||
class="px-3"
|
||||
:value="deductibleBoxValue" />
|
||||
</div>
|
||||
<siteFooter
|
||||
|
|
@ -104,6 +96,8 @@ import reviewBlock from '@/layouts/tpa-submit/review-block/review-block.vue';
|
|||
import deductibleBox from '@/layouts/tpa-submit/deductible-box/deductible-box.vue';
|
||||
import contactDetailsDrawer from '@/layouts/tpa-submit/contact-details-drawer/contact-details-drawer.vue';
|
||||
import siteFooter from '@/iss-components/site-footer/site-footer.vue';
|
||||
import alert from '@/ux-components/alert/alert.vue';
|
||||
import modal from '@/digital-components/modal/modal.vue';
|
||||
|
||||
// Supporting files
|
||||
import {
|
||||
|
|
@ -114,21 +108,16 @@ import {
|
|||
import { Form } from 'vee-validate';
|
||||
import BaseFormMixin from '@/mixins/base-form-mixin.js';
|
||||
import widgetFields from '@/constants/cms-widget-fields.js';
|
||||
import { useMainStore } from '@/store';
|
||||
import {
|
||||
toTitleCase,
|
||||
toDisplayPhoneNumber,
|
||||
formatAddress,
|
||||
formatAmountInDollars
|
||||
} from '@/helpers/text-helper.js';
|
||||
import {
|
||||
getDamageDisplayContent,
|
||||
getLocationAnswer
|
||||
} from '@/helpers/damage-review-content-generator.js';
|
||||
import damageLocationsSelected from '@/constants/damage-locations-selected.js';
|
||||
import { submitWorkOrder } from '@/helpers/order-helper.js';
|
||||
import bailoutMessage from '@/constants/bailoutMessage';
|
||||
import submitType from '@/constants/submit-type';
|
||||
import { modalPositions } from '@/constants/component-variants';
|
||||
|
||||
const VERIFYING_COVERAGE = 'Verifying coverage';
|
||||
|
||||
|
|
@ -143,7 +132,9 @@ export default {
|
|||
siteFooter,
|
||||
contactDetailsDrawer,
|
||||
// eslint-disable-next-line vue/no-reserved-component-names
|
||||
Form
|
||||
Form,
|
||||
alert,
|
||||
modal
|
||||
},
|
||||
mixins: [BaseFormMixin],
|
||||
async beforeRouteEnter(to, from, next) {
|
||||
|
|
@ -154,27 +145,19 @@ export default {
|
|||
});
|
||||
},
|
||||
data() {
|
||||
const { companyName } = useMainStore().order.serviceLocation.provider;
|
||||
return {
|
||||
sections: [],
|
||||
widget: {
|
||||
siteHeader: 'SiteHeaderWidget',
|
||||
siteSubHeader: 'SiteSubHeaderWidget',
|
||||
serviceSummary: 'ServiceSummaryContent',
|
||||
subheader: {
|
||||
vehicle: 'VehicleSubTitle',
|
||||
damage: 'DamageSubTitle',
|
||||
shop: 'PreferredShopSubTitle',
|
||||
contactInfo: 'ContactDetailsSubTitle'
|
||||
},
|
||||
damageLocations: 'DamageLocationsWidget',
|
||||
orderDetails: 'OrderDetailsContent',
|
||||
footer: 'SiteFooterWidget'
|
||||
footer: 'SiteFooterWidget',
|
||||
alertIncomplete: 'AlertIncompleteWidget',
|
||||
alertRecalWarning: 'AlertRecalWarningWidget',
|
||||
editShopLinkText: 'EditShopLinkTextWidget',
|
||||
contactDetails: 'ContactDetailsSectionWidget'
|
||||
},
|
||||
companyName,
|
||||
customValueMap: {
|
||||
glassShop: companyName
|
||||
}
|
||||
modalPositions
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -197,12 +180,6 @@ export default {
|
|||
);
|
||||
return getStringWithCustomValues(cmsContent, this.customValueMap);
|
||||
},
|
||||
serviceSummaryText() {
|
||||
return this.getCmsContent(
|
||||
this.widget.serviceSummary,
|
||||
widgetFields.TEXT_BLOCK_WIDGET.TEXT
|
||||
);
|
||||
},
|
||||
orderDetailsTitle() {
|
||||
return this.getCmsContent(
|
||||
this.widget.orderDetails,
|
||||
|
|
@ -227,53 +204,21 @@ export default {
|
|||
);
|
||||
},
|
||||
isVerified() {
|
||||
return useMainStore().isVerified;
|
||||
return this.mainStore.isVerified;
|
||||
},
|
||||
currentDeductible() {
|
||||
return useMainStore().order.currentDeductible;
|
||||
return this.mainStore.order.currentDeductible;
|
||||
},
|
||||
deductibleBoxValue() {
|
||||
return this.isVerified
|
||||
? formatAmountInDollars(this.currentDeductible)
|
||||
: VERIFYING_COVERAGE;
|
||||
},
|
||||
getVehicleLines() {
|
||||
const { year, make, model } = useMainStore().order.vehicle;
|
||||
const line = [year, make, model]
|
||||
.filter((v) => v != null && v !== '')
|
||||
.join(' ');
|
||||
return [line];
|
||||
},
|
||||
locationAnswers() {
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(this.widget.damageLocations);
|
||||
},
|
||||
driverSideDamageAnswers() {
|
||||
const answerContent = getLocationAnswer(
|
||||
damageLocationsSelected.DRIVER,
|
||||
this.locationAnswers
|
||||
);
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(answerContent?.SubWidgetName);
|
||||
},
|
||||
passengerSideDamageAnswers() {
|
||||
const answerContent = getLocationAnswer(
|
||||
damageLocationsSelected.PASSENGER,
|
||||
this.locationAnswers
|
||||
);
|
||||
return this.getInputQuestionWidgetAnswersNullSafe(answerContent?.SubWidgetName);
|
||||
},
|
||||
getDamageLines() {
|
||||
const { glassToReplace, isRepair } = useMainStore().order.damage;
|
||||
return getDamageDisplayContent(
|
||||
this.locationAnswers,
|
||||
this.driverSideDamageAnswers,
|
||||
this.passengerSideDamageAnswers,
|
||||
glassToReplace,
|
||||
isRepair
|
||||
);
|
||||
getPreferredShopTitle() {
|
||||
return toTitleCase(this.mainStore.order.serviceLocation.provider.companyName ?? '');
|
||||
},
|
||||
getPreferredShopLines() {
|
||||
const { phoneNumber, address } =
|
||||
useMainStore().order.serviceLocation.provider;
|
||||
const { phoneNumber, address } = this.mainStore.order.serviceLocation.provider;
|
||||
const { streetAddress, city, state, zipCode } = address;
|
||||
const displayAddress = formatAddress(
|
||||
streetAddress,
|
||||
|
|
@ -284,58 +229,86 @@ export default {
|
|||
);
|
||||
const displayPhoneNumber = toDisplayPhoneNumber(phoneNumber);
|
||||
return [
|
||||
toTitleCase(this.companyName ?? ''),
|
||||
displayAddress,
|
||||
displayPhoneNumber
|
||||
];
|
||||
},
|
||||
getEditShopLinkText() {
|
||||
return this.getCmsContent(
|
||||
this.widget.editShopLinkText,
|
||||
widgetFields.TEXT_BLOCK_WIDGET.TEXT
|
||||
);
|
||||
},
|
||||
getContactInfoTitle() {
|
||||
const cmsContent = this.getCmsContent(
|
||||
this.widget.contactDetails,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT
|
||||
);
|
||||
return getStringWithCustomValues(cmsContent, this.customValueMap);
|
||||
},
|
||||
getContactInfoLines() {
|
||||
const { firstName, lastName, emailAddress, servicePhone } =
|
||||
useMainStore().contactInfo;
|
||||
const cmsContent = this.getCmsContent(
|
||||
this.widget.contactDetails,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT
|
||||
);
|
||||
return [
|
||||
`${firstName} ${lastName}`,
|
||||
emailAddress ?? '',
|
||||
toDisplayPhoneNumber(servicePhone)
|
||||
getStringWithCustomValues(cmsContent, this.customValueMap)
|
||||
];
|
||||
},
|
||||
getEditContactInfoLinkText() {
|
||||
return this.getCmsContent(
|
||||
this.widget.contactDetails,
|
||||
widgetFields.CONTENT_GROUP_WIDGET.FOOTER_TEXT
|
||||
);
|
||||
},
|
||||
recalModalContent() {
|
||||
const widgetName = 'RecalModal';
|
||||
return {
|
||||
headerText: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.HEADER_TEXT),
|
||||
subHeaderText: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.SUBHEADER_TEXT),
|
||||
bodyText: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.BODY_TEXT),
|
||||
footerButtonText: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.FOOTER_TEXT),
|
||||
image: this.getCmsContent(widgetName, widgetFields.CONTENT_GROUP_WIDGET.IMAGE)
|
||||
}
|
||||
},
|
||||
recalibrationRequired() {
|
||||
return this.mainStore.hasRecalibrationPart;
|
||||
},
|
||||
customValueMap() {
|
||||
let contactPhone = toDisplayPhoneNumber(this.mainStore.contactInfo.servicePhone);
|
||||
if (this.mainStore.contactInfo.extension) {
|
||||
contactPhone += ` Ext. ${this.mainStore.contactInfo.extension}`;
|
||||
}
|
||||
return {
|
||||
glassShop: this.getPreferredShopTitle,
|
||||
contactPhone: contactPhone,
|
||||
contactEmail: this.mainStore.contactInfo.emailAddress ?? ''
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setSections() {
|
||||
const vehicleScenario = useMainStore().isPolicyVehicle
|
||||
? this.navigationScenarios.EDIT_POLICY_VEHICLE
|
||||
: this.navigationScenarios.EDIT_VEHICLE;
|
||||
this.sections = [
|
||||
this.getSection(
|
||||
this.widget.subheader.vehicle,
|
||||
this.getVehicleLines,
|
||||
() => this.navigate(vehicleScenario)
|
||||
),
|
||||
// eslint-disable-next-line max-len
|
||||
this.getSection(
|
||||
this.widget.subheader.damage,
|
||||
this.getDamageLines,
|
||||
() => this.navigate(this.navigationScenarios.EDIT_DAMAGE)
|
||||
),
|
||||
this.getSection(
|
||||
this.widget.subheader.shop,
|
||||
this.getPreferredShopTitle,
|
||||
this.getPreferredShopLines,
|
||||
() => this.navigate(this.navigationScenarios.EDIT_PREFERRED_SHOP)
|
||||
this.getEditShopLinkText,
|
||||
() => this.navigate(this.navigationScenarios.EDIT_PREFERRED_SHOP),
|
||||
),
|
||||
// eslint-disable-next-line max-len
|
||||
this.getSection(
|
||||
this.widget.subheader.contactInfo,
|
||||
this.getContactInfoTitle,
|
||||
this.getContactInfoLines,
|
||||
this.getEditContactInfoLinkText,
|
||||
this.openContactDetailsModal
|
||||
)
|
||||
];
|
||||
},
|
||||
getSection(widgetName, lines, onClick) {
|
||||
getSection(title, lines, editLinkText, onClick) {
|
||||
return {
|
||||
title: this.getCmsContent(
|
||||
widgetName,
|
||||
widgetFields.TEXT_BLOCK_WIDGET.TEXT
|
||||
),
|
||||
title: title,
|
||||
lines,
|
||||
editLinkText,
|
||||
onClickEdit: onClick
|
||||
};
|
||||
},
|
||||
|
|
@ -344,7 +317,7 @@ export default {
|
|||
await submitWorkOrder({ submitType: submitType.TPA }).then(() => {
|
||||
this.navigate(this.navigationScenarios.CLICKED_FORWARD);
|
||||
}).catch((submitError) => {
|
||||
useMainStore().setBailout(bailoutMessage.saveSessionError(submitError.data));
|
||||
this.mainStore.setBailout(bailoutMessage.saveSessionError(submitError.data));
|
||||
this.navigate(
|
||||
this.navigationScenarios.SAVE_SESSION_FAILED,
|
||||
this.$route,
|
||||
|
|
@ -372,6 +345,12 @@ export default {
|
|||
},
|
||||
openContactDetailsModal() {
|
||||
this.$refs.contactDetailsDrawer.openModal();
|
||||
},
|
||||
openRecalModal() {
|
||||
this.$refs.recalModal.openModal();
|
||||
},
|
||||
closeRecalModal() {
|
||||
this.$refs.recalModal.closeModal();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -387,26 +366,69 @@ export default {
|
|||
}
|
||||
|
||||
.tpa-submit {
|
||||
#tpaSubmitOrderDetailsBody {
|
||||
p {
|
||||
font-size: .875rem;
|
||||
}
|
||||
}
|
||||
.tpa-submit__title--line-height {
|
||||
line-height: map-get($spacers, 6);
|
||||
.alert-warning {
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: 0rem;
|
||||
}
|
||||
|
||||
.text-color--darker-gray {
|
||||
color: $darker-gray;
|
||||
.tpa-submit-title {
|
||||
font-size: 1.25rem;
|
||||
color: $black;
|
||||
font-weight: 400;
|
||||
margin-top: 1.25rem;
|
||||
margin-bottom: .625rem;
|
||||
}
|
||||
|
||||
.text-color--black {
|
||||
.recal-alert {
|
||||
margin-bottom: 4rem;
|
||||
}
|
||||
|
||||
b {
|
||||
font-weight: $font-weight-bold;
|
||||
color: $black;
|
||||
}
|
||||
|
||||
hr {
|
||||
opacity: 1;
|
||||
color: $gray-350;
|
||||
margin: 1.875rem 0rem;
|
||||
}
|
||||
|
||||
.fw-bold {
|
||||
color: $black;
|
||||
}
|
||||
|
||||
.order-details-title {
|
||||
margin-bottom: .625rem;
|
||||
}
|
||||
|
||||
.modal.recal-modal .modal-dialog {
|
||||
.modal-header {
|
||||
justify-content: start;
|
||||
margin: 0rem;
|
||||
padding: 1.25rem 1.25rem .625rem 1.25rem;
|
||||
.modal-title {
|
||||
font-weight: $font-weight-bolder;
|
||||
font-size: .875rem;
|
||||
line-height: 1.25rem;
|
||||
text-align: start;
|
||||
justify-content: start;
|
||||
}
|
||||
.btn-close {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.modal-body {
|
||||
padding: 0rem 1.25rem 1.25rem 1.25rem;
|
||||
b {
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
.recal-modal-subheader {
|
||||
font-weight: $font-weight-bold;
|
||||
color: $black;
|
||||
}
|
||||
.recal-modal-image {
|
||||
margin: 1.25rem 0rem
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -310,7 +310,14 @@ export default {
|
|||
this.mainStore.updatePolicyData(this.welcomePageModel);
|
||||
const promises = [];
|
||||
promises.push(this.configureZip().then(async () => await this.mainStore.getBillToInfo()));
|
||||
if (!this.mainStore.order.loadedFromCookie) {
|
||||
|
||||
// Clear duplicate orders if navigating away from the welcome page after visiting duplicate check page.
|
||||
if (this.mainStore.order.visitedDuplicateCheckPage) {
|
||||
this.mainStore.clearDuplicateOrders();
|
||||
}
|
||||
|
||||
// Skip duplicate check if loaded from cookie or already visited duplicate check page.
|
||||
if (!this.mainStore.order.loadedFromCookie && !this.mainStore.order.visitedDuplicateCheckPage) {
|
||||
promises.push(this.mainStore.getDuplicateReferrals());
|
||||
}
|
||||
promises.push(this.mainStore.getCoveragePolicyInfo());
|
||||
|
|
@ -472,6 +479,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import '@/styles/ux-variables-svg-strings.scss';
|
||||
form {
|
||||
.container-fluid {
|
||||
display: flex;
|
||||
|
|
@ -489,6 +497,22 @@ form {
|
|||
|
||||
.form-group {
|
||||
margin-top: 1.25rem;
|
||||
|
||||
:deep(.input-wrapper) {
|
||||
input[type="date"] {
|
||||
max-height: 3rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-error {
|
||||
:deep(.input-wrapper) {
|
||||
input[type="date"]::-webkit-calendar-picker-indicator {
|
||||
background-color: $svg-calendar-error-fill-color;
|
||||
// eslint-disable-next-line max-len
|
||||
background-image: url($svg-error-calendar-graphic);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,8 @@ const navigationScenarios = Object.freeze({
|
|||
|
||||
// Policy Holder Details
|
||||
CLICKED_FORWARD_POLICY_VERIFIED: 'CLICKED_FORWARD_POLICY_VERIFIED',
|
||||
CLICKED_BACK_POLICY_UNVERIFIED: 'CLICKED_BACK_POLICY_UNVERIFIED',
|
||||
CLICKED_BACK_POLICY_VERIFIED: 'CLICKED_BACK_POLICY_VERIFIED',
|
||||
|
||||
// Policy Vehicle
|
||||
CLICKED_FORWARD_LISTED_VEHICLE: 'CLICKED_FORWARD_LISTED_VEHICLE',
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ const routingTable = () => [
|
|||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
destinationIssPageValue: issPageValues.WELCOME_PAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_BAILOUT,
|
||||
|
|
@ -26,7 +26,7 @@ const routingTable = () => [
|
|||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_SELECTION
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_REPAIR,
|
||||
|
|
@ -386,7 +386,7 @@ const routingTable = () => [
|
|||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
destinationIssPageValue: issPageValues.VEHICLE_SELECTION
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_DUPLICATES,
|
||||
|
|
@ -394,7 +394,7 @@ const routingTable = () => [
|
|||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
destinationIssPageValue: issPageValues.VEHICLE_SELECTION
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
|
|
@ -423,7 +423,7 @@ const routingTable = () => [
|
|||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
destinationIssPageValue: issPageValues.VEHICLE_SELECTION
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED_NO_VEHICLES,
|
||||
|
|
@ -435,7 +435,7 @@ const routingTable = () => [
|
|||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_POLICY_VEHICLE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_LOADED_DUPLICATE_WITH_NON_POLICY_VEHICLE,
|
||||
|
|
@ -451,16 +451,20 @@ const routingTable = () => [
|
|||
issPageValue: issPageValues.POLICY_HOLDER_DETAILS,
|
||||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
scenario: navigationScenarios.CLICKED_BACK_POLICY_UNVERIFIED,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_SELECTION
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK_POLICY_VERIFIED,
|
||||
destinationIssPageValue: issPageValues.WELCOME_PAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_UNVERIFIED,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_SELECTION
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_POLICY_VERIFIED,
|
||||
destinationIssPageValue: issPageValues.POLICY_VEHICLES
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
@ -473,7 +477,7 @@ const routingTable = () => [
|
|||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_LISTED_VEHICLE,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_NON_LISTED_VEHICLE,
|
||||
|
|
@ -776,11 +780,11 @@ const routingTable = () => [
|
|||
maps: [
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_BACK,
|
||||
destinationIssPageValue: issPageValues.POLICY_VEHICLES
|
||||
destinationIssPageValue: issPageValues.WELCOME_PAGE
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD,
|
||||
destinationIssPageValue: issPageValues.VEHICLE_DAMAGE
|
||||
destinationIssPageValue: issPageValues.POLICY_HOLDER_DETAILS
|
||||
},
|
||||
{
|
||||
scenario: navigationScenarios.CLICKED_FORWARD_WITH_CAR_ID_NOT_FOUND,
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ describe('Router', () => {
|
|||
router.push = jest.fn();
|
||||
|
||||
router.navigate(scenario, currentRoute);
|
||||
expect(router.push.mock.calls[0][0].query.issPage).toBe(issPageValues.POLICY_HOLDER_DETAILS);
|
||||
expect(router.push.mock.calls[0][0].query.issPage).toBe(issPageValues.VEHICLE_SELECTION);
|
||||
});
|
||||
|
||||
it('Should set state as expected', () => {
|
||||
|
|
|
|||
|
|
@ -197,6 +197,7 @@ export const getDefaultState = () => ({
|
|||
homePhone: null,
|
||||
alternativePhone: null,
|
||||
servicePhone: null,
|
||||
extension: null,
|
||||
requestTextUpdates: false,
|
||||
notesForTechnician: ''
|
||||
},
|
||||
|
|
@ -225,7 +226,8 @@ export const getDefaultState = () => ({
|
|||
loadedFromCookie: false,
|
||||
loadedFromDupeCheck: null,
|
||||
loadedSessionClearedPreviousData: null,
|
||||
availableVaps: null
|
||||
availableVaps: null,
|
||||
visitedDuplicateCheckPage: false
|
||||
},
|
||||
applicationUser: {
|
||||
experiments: [],
|
||||
|
|
@ -354,6 +356,7 @@ export const useMainStore = defineStore({
|
|||
homePhone: s.order.contactInfo.homePhone,
|
||||
alternativePhone: s.order.contactInfo.alternativePhone,
|
||||
servicePhone: s.order.contactInfo.servicePhone,
|
||||
extension: s.order.contactInfo.extension,
|
||||
requestTextUpdates: s.order.contactInfo.requestTextUpdates ?? false,
|
||||
notesForTechnician: s.order.contactInfo.notesForTechnician
|
||||
}),
|
||||
|
|
@ -595,6 +598,12 @@ export const useMainStore = defineStore({
|
|||
return Promise.reject(e);
|
||||
}
|
||||
},
|
||||
clearDuplicateOrders() {
|
||||
this.applicationUser.duplicateOrders = [];
|
||||
},
|
||||
updateDuplicateCheckVisited(visited) {
|
||||
this.order.visitedDuplicateCheckPage = visited;
|
||||
},
|
||||
updateCoverageStatus(status) {
|
||||
this.order.insuranceCoverage.coverageStatus = status;
|
||||
},
|
||||
|
|
@ -1012,14 +1021,13 @@ export const useMainStore = defineStore({
|
|||
});
|
||||
},
|
||||
|
||||
getProviders(serviceZipCode) {
|
||||
getProviders(serviceZipCode, shopRadiusInMiles = 100) {
|
||||
const { carId, isBigTruck } = this.order.vehicle;
|
||||
const damageType = this.damage.isRepair ? 'Repair' : 'Replace';
|
||||
const { parentAccountNumber } = this.order;
|
||||
const partsWithRecal = getTopLevelGlassPartsWithRecal(this.order.lineItems.glassParts);
|
||||
const windshieldPartWithRecal = partsWithRecal?.length > 0 ? partsWithRecal[0] : null;
|
||||
const safeliteOnly = true;
|
||||
const shopRadiusInMiles = 100;
|
||||
|
||||
let url = `${endpoints.GetProviders.url}/${serviceZipCode}/${damageType}/${shopRadiusInMiles}/${parentAccountNumber}/${safeliteOnly}/${carId}`;
|
||||
if (windshieldPartWithRecal) {
|
||||
|
|
@ -1456,7 +1464,7 @@ export const useMainStore = defineStore({
|
|||
emailAddress: contactInfo.emailAddress || customer.emailAddress,
|
||||
firstName: contactInfo.firstName || customer.firstName,
|
||||
lastName: contactInfo.lastName || customer.lastName,
|
||||
homePhone: contactInfo.homePhone,
|
||||
homePhone: contactInfo.extension && contactInfo.homePhone ? contactInfo.homePhone + contactInfo.extension : contactInfo.homePhone,
|
||||
servicePhone: contactInfo.servicePhone,
|
||||
alternativePhone: contactInfo.alternativePhone,
|
||||
isSmsOptIn: contactInfo.requestTextUpdates ?? false
|
||||
|
|
@ -1590,7 +1598,8 @@ export const useMainStore = defineStore({
|
|||
order.contactInfo.firstName = data?.customer?.firstName;
|
||||
order.contactInfo.lastName = data?.customer?.lastName;
|
||||
order.contactInfo.emailAddress = data?.customer?.emailAddress;
|
||||
order.contactInfo.homePhone = data?.customer?.homePhone;
|
||||
order.contactInfo.extension = data?.customer?.homePhone?.slice(10);
|
||||
order.contactInfo.homePhone = data?.customer?.homePhone?.slice(0, 10);
|
||||
order.contactInfo.servicePhone = data?.customer?.servicePhone;
|
||||
order.contactInfo.alternativePhone = data?.customer?.alternativePhone;
|
||||
order.contactInfo.requestTextUpdates = data?.customer?.isSmsOptIn;
|
||||
|
|
@ -1658,7 +1667,8 @@ export const useMainStore = defineStore({
|
|||
order.contactInfo.firstName = data?.customer?.firstName;
|
||||
order.contactInfo.lastName = data?.customer?.lastName;
|
||||
order.contactInfo.emailAddress = data?.customer?.emailAddress;
|
||||
order.contactInfo.homePhone = data?.customer?.homePhone;
|
||||
order.contactInfo.extension = data?.customer?.homePhone?.slice(10);
|
||||
order.contactInfo.homePhone = data?.customer?.homePhone?.slice(0, 10);
|
||||
order.contactInfo.servicePhone = data?.customer?.servicePhone;
|
||||
order.contactInfo.alternativePhone = data?.customer?.alternativePhone;
|
||||
order.contactInfo.requestTextUpdates = data?.customer?.isSmsOptIn;
|
||||
|
|
@ -1720,6 +1730,7 @@ export const useMainStore = defineStore({
|
|||
order.eon = data?.eon;
|
||||
order.workOrderId = data?.workOrderId;
|
||||
order.loadedFromCookie = true;
|
||||
order.visitedDuplicateCheckPage = true;
|
||||
order.loadedSessionClearedPreviousData = false;
|
||||
issConfig.enableContinueFromCookie = false;
|
||||
this.updateIsSafeliteProvider(data?.provider?.isSafeliteProvider);
|
||||
|
|
@ -2042,6 +2053,7 @@ export const useMainStore = defineStore({
|
|||
this.order.carrierPhoneNumber = null;
|
||||
this.order.customerPortalLoginToken = null;
|
||||
this.order.loadedFromCookie = false;
|
||||
this.order.visitedDuplicateCheckPage = false;
|
||||
},
|
||||
|
||||
resetPolicy() {
|
||||
|
|
@ -2096,6 +2108,7 @@ export const useMainStore = defineStore({
|
|||
this.order.contactInfo.homePhone = null;
|
||||
this.order.contactInfo.alternativePhone = null;
|
||||
this.order.contactInfo.servicePhone = null;
|
||||
this.order.contactInfo.extension = null;
|
||||
this.order.contactInfo.requestTextUpdates = false;
|
||||
this.order.contactInfo.notesForTechnician = '';
|
||||
},
|
||||
|
|
@ -2291,6 +2304,7 @@ export const useMainStore = defineStore({
|
|||
this.order.customer.address.zipCode = customerQuestions.addressQuestions.zipCode;
|
||||
this.order.customer.firstName = customerQuestions.firstName;
|
||||
this.order.customer.lastName = customerQuestions.lastName;
|
||||
this.order.customer.emailAddress = customerQuestions.email;
|
||||
this.order.serviceLocation.zipCode = customerQuestions.addressQuestions.zipCode;
|
||||
},
|
||||
updateIsSafeliteProvider(isSafelite) {
|
||||
|
|
@ -2576,6 +2590,7 @@ export const useMainStore = defineStore({
|
|||
contact.homePhone = phoneNumbers.home !== undefined ? phoneNumbers.home : contact.homePhone;
|
||||
contact.alternativePhone = phoneNumbers.alternative !== undefined ? phoneNumbers.alternative : contact.alternativePhone;
|
||||
contact.servicePhone = phoneNumbers.service !== undefined ? phoneNumbers.service : contact.servicePhone;
|
||||
contact.extension = phoneNumbers.extension !== undefined ? phoneNumbers.extension : contact.extension;
|
||||
},
|
||||
|
||||
GetExperimentsByUser(userId) {
|
||||
|
|
|
|||
|
|
@ -494,18 +494,21 @@ describe('Store', () => {
|
|||
const homePhone = getRandomInt(1000000000, 9999999999);
|
||||
const servicePhone = getRandomInt(1000000000, 9999999999);
|
||||
const altPhone = getRandomInt(1000000000, 9999999999);
|
||||
const extension = getRandomInt(10000, 99999);
|
||||
|
||||
// Act
|
||||
store.updatePhoneNumbers({
|
||||
home: homePhone,
|
||||
service: servicePhone,
|
||||
alternative: altPhone
|
||||
alternative: altPhone,
|
||||
extension: extension
|
||||
});
|
||||
|
||||
// Assert
|
||||
expect(store.contactInfo.homePhone).toEqual(homePhone);
|
||||
expect(store.contactInfo.servicePhone).toEqual(servicePhone);
|
||||
expect(store.contactInfo.alternativePhone).toEqual(altPhone);
|
||||
expect(store.contactInfo.extension).toEqual(extension);
|
||||
});
|
||||
it('All null values => contact info set in store to all nulls', () => {
|
||||
// Act
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ body {
|
|||
font-size: 16px;
|
||||
letter-spacing: $letter-spacing-primary;
|
||||
background-color: #fff;
|
||||
color: #4d5151;
|
||||
color: $body-color;
|
||||
|
||||
.container-fluid {
|
||||
.prevent-squish {
|
||||
|
|
@ -179,6 +179,10 @@ body {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.site-sub-header-container {
|
||||
margin-top: 1.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
:root {
|
||||
|
|
|
|||
|
|
@ -115,21 +115,3 @@ caption,
|
|||
font-weight: 800;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Urbanist";
|
||||
src:
|
||||
url("@/assets/fonts/Urbanist-MediumItalic.woff2") format("woff2"),
|
||||
url("@/assets/fonts/Urbanist-MediumItalic.woff") format("woff");
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: "Urbanist";
|
||||
src:
|
||||
url("@/assets/fonts/Urbanist-BoldItalic.woff2") format("woff2"),
|
||||
url("@/assets/fonts/Urbanist-BoldItalic.woff") format("woff");
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
|
|
@ -14,17 +14,17 @@ html {
|
|||
border-radius: 60px;
|
||||
|
||||
.button-content {
|
||||
border: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
@include box-shadow-hover($red-200);
|
||||
z-index: 5;
|
||||
border: 1px solid $red;
|
||||
}
|
||||
|
||||
input[type="radio"]:focus+.list-button-content {
|
||||
box-shadow: 0 0 0 2.5px $red;
|
||||
}
|
||||
&:not(.selected):not(.no-hover):hover {
|
||||
position: relative;
|
||||
@include box-shadow-hover($red-200);
|
||||
z-index: 5;
|
||||
}
|
||||
}
|
||||
|
||||
&.list-card {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
.base-input-button {
|
||||
&:not(.has-error):hover {
|
||||
&:not(.disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&:not(.has-error):hover {
|
||||
&.list-button,
|
||||
&.list-button-horizontal,
|
||||
&.list-card {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
$svg-calendar-picker: "data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M14.1762 1.52764H13.7656V1.50352C13.7656 1.10476 13.6076 0.722334 13.3263 0.44037C13.0451 0.158406 12.6636 0 12.2659 0C11.8681 0 11.4866 0.158406 11.2054 0.44037C10.9241 0.722334 10.7661 1.10476 10.7661 1.50352V1.52764H5.42476V1.50352C5.42476 1.10476 5.26675 0.722334 4.9855 0.44037C4.70424 0.158406 4.32277 0 3.92501 0C3.52725 0 3.14579 0.158406 2.86453 0.44037C2.58327 0.722334 2.42526 1.10476 2.42526 1.50352V1.52764H1.82376C1.34046 1.52891 0.877316 1.72195 0.53557 2.06455C0.193824 2.40716 0.00127018 2.87146 0 3.35598V14.1717C0.0016909 14.656 0.194379 15.1201 0.536035 15.4626C0.87769 15.8051 1.34059 15.9983 1.82376 16H14.1746C14.6581 15.9987 15.1214 15.8057 15.4634 15.4632C15.8054 15.1206 15.9983 14.6563 16 14.1717V3.35598C15.9987 2.87146 15.8062 2.40716 15.4644 2.06455C15.1227 1.72195 14.6595 1.52891 14.1762 1.52764ZM11.8889 1.50352C11.8889 1.4033 11.9286 1.30718 11.9993 1.23631C12.07 1.16544 12.1659 1.12563 12.2659 1.12563C12.3658 1.12563 12.4617 1.16544 12.5324 1.23631C12.6031 1.30718 12.6428 1.4033 12.6428 1.50352V2.99899C12.6428 3.09922 12.6031 3.19534 12.5324 3.2662C12.4617 3.33707 12.3658 3.37688 12.2659 3.37688C12.1659 3.37688 12.07 3.33707 11.9993 3.2662C11.9286 3.19534 11.8889 3.09922 11.8889 2.99899V1.50352ZM3.54807 1.50352C3.54807 1.4033 3.58778 1.30718 3.65847 1.23631C3.72916 1.16544 3.82504 1.12563 3.92501 1.12563C4.02498 1.12563 4.12086 1.16544 4.19155 1.23631C4.26224 1.30718 4.30195 1.4033 4.30195 1.50352V2.99899C4.30195 3.09922 4.26224 3.19534 4.19155 3.2662C4.12086 3.33707 4.02498 3.37688 3.92501 3.37688C3.82504 3.37688 3.72916 3.33707 3.65847 3.2662C3.58778 3.19534 3.54807 3.09922 3.54807 2.99899V1.50352ZM14.8772 14.1717C14.8747 14.3573 14.8001 14.5345 14.6691 14.6658C14.5382 14.797 14.3614 14.8719 14.1762 14.8744H1.82536C1.63995 14.8723 1.4627 14.7976 1.33144 14.6663C1.20018 14.5351 1.12531 14.3575 1.12281 14.1717V6.59296H14.8772V14.1717Z' fill='%23167CAC'/%3E%3Cpath d='M2.33063 11.282H3.93464V12.6006C3.93464 12.7499 3.99379 12.8931 4.09907 12.9986C4.20435 13.1041 4.34715 13.1634 4.49604 13.1634C4.64494 13.1634 4.78773 13.1041 4.89301 12.9986C4.9983 12.8931 5.05745 12.7499 5.05745 12.6006V11.282H7.46346V12.6006C7.46346 12.7499 7.52261 12.8931 7.62789 12.9986C7.73318 13.1041 7.87597 13.1634 8.02486 13.1634C8.17376 13.1634 8.31655 13.1041 8.42184 12.9986C8.52712 12.8931 8.58627 12.7499 8.58627 12.6006V11.282H10.9923V12.6006C10.9923 12.7499 11.0514 12.8931 11.1567 12.9986C11.262 13.1041 11.4048 13.1634 11.5537 13.1634C11.7026 13.1634 11.8454 13.1041 11.9507 12.9986C12.0559 12.8931 12.1151 12.7499 12.1151 12.6006V11.282H13.7191C13.868 11.282 14.0108 11.2227 14.1161 11.1172C14.2214 11.0116 14.2805 10.8685 14.2805 10.7192C14.2805 10.57 14.2214 10.4268 14.1161 10.3213C14.0108 10.2157 13.868 10.1564 13.7191 10.1564H12.1151V8.84425C12.1151 8.69498 12.0559 8.55183 11.9507 8.44628C11.8454 8.34073 11.7026 8.28143 11.5537 8.28143C11.4048 8.28143 11.262 8.34073 11.1567 8.44628C11.0514 8.55183 10.9923 8.69498 10.9923 8.84425V10.1628H8.58627V8.84425C8.58627 8.69498 8.52712 8.55183 8.42184 8.44628C8.31655 8.34073 8.17376 8.28143 8.02486 8.28143C7.87597 8.28143 7.73318 8.34073 7.62789 8.44628C7.52261 8.55183 7.46346 8.69498 7.46346 8.84425V10.1628H5.05745V8.84425C5.05745 8.69498 4.9983 8.55183 4.89301 8.44628C4.78773 8.34073 4.64494 8.28143 4.49604 8.28143C4.34715 8.28143 4.20435 8.34073 4.09907 8.44628C3.99379 8.55183 3.93464 8.69498 3.93464 8.84425V10.1628H2.33063C2.18174 10.1628 2.03894 10.2221 1.93366 10.3277C1.82837 10.4332 1.76923 10.5764 1.76923 10.7257C1.76923 10.8749 1.82837 11.0181 1.93366 11.1236C2.03894 11.2292 2.18174 11.2885 2.33063 11.2885V11.282Z' fill='%23167CAC'/%3E%3C/svg%3E";
|
||||
$svg-error-calendar-graphic: "data:image/svg+xml,%3Csvg width='16' height='16' viewBox='0 0 16 16' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M14.1762 1.52764H13.7656V1.50352C13.7656 1.10476 13.6076 0.722334 13.3263 0.44037C13.0451 0.158406 12.6636 0 12.2659 0C11.8681 0 11.4866 0.158406 11.2054 0.44037C10.9241 0.722334 10.7661 1.10476 10.7661 1.50352V1.52764H5.42476V1.50352C5.42476 1.10476 5.26675 0.722334 4.9855 0.44037C4.70424 0.158406 4.32277 0 3.92501 0C3.52725 0 3.14579 0.158406 2.86453 0.44037C2.58327 0.722334 2.42526 1.10476 2.42526 1.50352V1.52764H1.82376C1.34046 1.52891 0.877316 1.72195 0.53557 2.06455C0.193824 2.40716 0.00127018 2.87146 0 3.35598V14.1717C0.0016909 14.656 0.194379 15.1201 0.536035 15.4626C0.87769 15.8051 1.34059 15.9983 1.82376 16H14.1746C14.6581 15.9987 15.1214 15.8057 15.4634 15.4632C15.8054 15.1206 15.9983 14.6563 16 14.1717V3.35598C15.9987 2.87146 15.8062 2.40716 15.4644 2.06455C15.1227 1.72195 14.6595 1.52891 14.1762 1.52764ZM11.8889 1.50352C11.8889 1.4033 11.9286 1.30718 11.9993 1.23631C12.07 1.16544 12.1659 1.12563 12.2659 1.12563C12.3658 1.12563 12.4617 1.16544 12.5324 1.23631C12.6031 1.30718 12.6428 1.4033 12.6428 1.50352V2.99899C12.6428 3.09922 12.6031 3.19534 12.5324 3.2662C12.4617 3.33707 12.3658 3.37688 12.2659 3.37688C12.1659 3.37688 12.07 3.33707 11.9993 3.2662C11.9286 3.19534 11.8889 3.09922 11.8889 2.99899V1.50352ZM3.54807 1.50352C3.54807 1.4033 3.58778 1.30718 3.65847 1.23631C3.72916 1.16544 3.82504 1.12563 3.92501 1.12563C4.02498 1.12563 4.12086 1.16544 4.19155 1.23631C4.26224 1.30718 4.30195 1.4033 4.30195 1.50352V2.99899C4.30195 3.09922 4.26224 3.19534 4.19155 3.2662C4.12086 3.33707 4.02498 3.37688 3.92501 3.37688C3.82504 3.37688 3.72916 3.33707 3.65847 3.2662C3.58778 3.19534 3.54807 3.09922 3.54807 2.99899V1.50352ZM14.8772 14.1717C14.8747 14.3573 14.8001 14.5345 14.6691 14.6658C14.5382 14.797 14.3614 14.8719 14.1762 14.8744H1.82536C1.63995 14.8723 1.4627 14.7976 1.33144 14.6663C1.20018 14.5351 1.12531 14.3575 1.12281 14.1717V6.59296H14.8772V14.1717Z' fill='" + $svg-calendar-error-stroke-color + "'/%3E%3Cpath d='M2.33063 11.282H3.93464V12.6006C3.93464 12.7499 3.99379 12.8931 4.09907 12.9986C4.20435 13.1041 4.34715 13.1634 4.49604 13.1634C4.64494 13.1634 4.78773 13.1041 4.89301 12.9986C4.9983 12.8931 5.05745 12.7499 5.05745 12.6006V11.282H7.46346V12.6006C7.46346 12.7499 7.52261 12.8931 7.62789 12.9986C7.73318 13.1041 7.87597 13.1634 8.02486 13.1634C8.17376 13.1634 8.31655 13.1041 8.42184 12.9986C8.52712 12.8931 8.58627 12.7499 8.58627 12.6006V11.282H10.9923V12.6006C10.9923 12.7499 11.0514 12.8931 11.1567 12.9986C11.262 13.1041 11.4048 13.1634 11.5537 13.1634C11.7026 13.1634 11.8454 13.1041 11.9507 12.9986C12.0559 12.8931 12.1151 12.7499 12.1151 12.6006V11.282H13.7191C13.868 11.282 14.0108 11.2227 14.1161 11.1172C14.2214 11.0116 14.2805 10.8685 14.2805 10.7192C14.2805 10.57 14.2214 10.4268 14.1161 10.3213C14.0108 10.2157 13.868 10.1564 13.7191 10.1564H12.1151V8.84425C12.1151 8.69498 12.0559 8.55183 11.9507 8.44628C11.8454 8.34073 11.7026 8.28143 11.5537 8.28143C11.4048 8.28143 11.262 8.34073 11.1567 8.44628C11.0514 8.55183 10.9923 8.69498 10.9923 8.84425V10.1628H8.58627V8.84425C8.58627 8.69498 8.52712 8.55183 8.42184 8.44628C8.31655 8.34073 8.17376 8.28143 8.02486 8.28143C7.87597 8.28143 7.73318 8.34073 7.62789 8.44628C7.52261 8.55183 7.46346 8.69498 7.46346 8.84425V10.1628H5.05745V8.84425C5.05745 8.69498 4.9983 8.55183 4.89301 8.44628C4.78773 8.34073 4.64494 8.28143 4.49604 8.28143C4.34715 8.28143 4.20435 8.34073 4.09907 8.44628C3.99379 8.55183 3.93464 8.69498 3.93464 8.84425V10.1628H2.33063C2.18174 10.1628 2.03894 10.2221 1.93366 10.3277C1.82837 10.4332 1.76923 10.5764 1.76923 10.7257C1.76923 10.8749 1.82837 11.0181 1.93366 11.1236C2.03894 11.2292 2.18174 11.2885 2.33063 11.2885V11.282Z' fill='" + $svg-calendar-error-stroke-color + "'/%3E%3C/svg%3E";
|
||||
$svg-date-picker-nav-back-button: "data:image/svg+xml,%3Csvg width='7' height='12' viewBox='0 0 7 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M0.331685 6.00121C0.330445 5.82446 0.399256 5.65442 0.523053 5.52832L5.84499 0.198256C5.97188 0.0713149 6.14397 -8.63821e-08 6.32341 -6.72174e-08C6.50285 -4.80527e-08 6.67495 0.071315 6.80183 0.198256C6.92872 0.325198 7 0.497368 7 0.67689C7 0.856412 6.92872 1.02858 6.80183 1.15552L1.94874 6.00121L6.80183 10.8526C6.92745 10.9796 6.99751 11.1512 6.99662 11.3299C6.99572 11.5085 6.92393 11.6794 6.79705 11.8051C6.67016 11.9308 6.49857 12.0009 6.32003 12C6.14148 11.9991 5.97061 11.9273 5.84499 11.8003L0.526881 6.47601C0.401568 6.34983 0.331375 6.17908 0.331685 6.00121Z' fill='%231574A1'/%3E%3C/svg%3E%0A";
|
||||
$svg-date-picker-forward-button: "data:image/svg+xml,%3Csvg width='7' height='12' viewBox='0 0 7 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M6.66831 5.99879C6.66955 6.17554 6.60074 6.34558 6.47695 6.47168L1.15501 11.8017C1.02812 11.9287 0.85603 12 0.676587 12C0.497145 12 0.325053 11.9287 0.198168 11.8017C0.0712831 11.6748 7.268e-09 11.5026 8.07183e-09 11.3231C8.87567e-09 11.1436 0.0712831 10.9714 0.198168 10.8445L5.05126 5.99879L0.198168 1.14736C0.0725521 1.02042 0.00248585 0.848755 0.00338306 0.670131C0.00428028 0.491506 0.0760674 0.320554 0.202952 0.194881C0.329837 0.0692091 0.501426 -0.000888818 0.679971 9.54485e-06C0.858515 0.000906955 1.02939 0.0727263 1.15501 0.199668L6.47312 5.52399C6.59843 5.65017 6.66862 5.82092 6.66831 5.99879Z' fill='%231574A1'/%3E%3C/svg%3E%0A";
|
||||
$svg-drop-off-alert: "data:image/svg+xml,%3Csvg viewBox='0 0 12 12' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cg clip-path='url(%23clip0_13957_112512)'%3E%3Cpath d='M5.99865 0C4.81147 4.82643e-07 3.65095 0.352111 2.66392 1.01179C1.67688 1.67146 0.907678 2.60907 0.45361 3.70599C-0.000459241 4.80291 -0.11899 6.00986 0.113013 7.17415C0.345015 8.33845 0.917126 9.40778 1.75697 10.2469C2.59682 11.086 3.66666 11.6571 4.83117 11.8881C5.99567 12.119 7.20251 11.9994 8.29902 11.5443C9.39553 11.0893 10.3324 10.3192 10.9912 9.33159C11.65 8.34396 12.0011 7.18313 12 5.99594C11.9971 4.40566 11.3638 2.88142 10.2388 1.75742C9.11375 0.633431 7.58894 0.00143011 5.99865 0V0ZM5.99865 11.2478C4.96135 11.2473 3.94748 10.9392 3.08518 10.3627C2.22288 9.7861 1.55085 8.96685 1.15401 8.00846C0.75718 7.05006 0.653353 5.99554 0.855656 4.97815C1.05796 3.96077 1.55731 3.02618 2.29061 2.29251C3.0239 1.55884 3.95823 1.059 4.97551 0.856176C5.99279 0.653349 7.04737 0.756633 8.00597 1.15297C8.96457 1.54931 9.78416 2.22092 10.3612 3.08293C10.9382 3.94493 11.2467 4.95864 11.2478 5.99594C11.2478 7.38835 10.6949 8.72377 9.71053 9.70861C8.7262 10.6934 7.39106 11.2471 5.99865 11.2478V11.2478Z' fill='%2306577C'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M6.22736 8.84695C6.30613 8.76818 6.35038 8.66135 6.35038 8.54996V5.30996C6.35038 5.19857 6.30613 5.09174 6.22736 5.01298C6.1486 4.93421 6.04177 4.88996 5.93038 4.88996C5.81899 4.88996 5.71216 4.93421 5.63339 5.01298C5.55463 5.09174 5.51038 5.19857 5.51038 5.30996V8.54996C5.51038 8.66135 5.55463 8.76818 5.63339 8.84695C5.71216 8.92571 5.81899 8.96996 5.93038 8.96996C6.04177 8.96996 6.1486 8.92571 6.22736 8.84695ZM5.69704 3.97918C5.76611 4.02533 5.84731 4.04996 5.93038 4.04996C5.98558 4.05012 6.04026 4.03936 6.09129 4.01831C6.14232 3.99726 6.18868 3.96633 6.22771 3.9273C6.26675 3.88827 6.29768 3.8419 6.31873 3.79088C6.33978 3.73985 6.35053 3.68516 6.35038 3.62996C6.35038 3.54689 6.32574 3.46569 6.27959 3.39662C6.23344 3.32755 6.16785 3.27372 6.0911 3.24193C6.01436 3.21014 5.92991 3.20183 5.84844 3.21803C5.76697 3.23424 5.69213 3.27424 5.63339 3.33298C5.57465 3.39171 5.53465 3.46655 5.51845 3.54802C5.50224 3.6295 5.51056 3.71394 5.54235 3.79069C5.57414 3.86743 5.62797 3.93303 5.69704 3.97918Z' fill='%2306577C'/%3E%3C/g%3E%3Cdefs%3E%3CclipPath id='clip0_13957_112512'%3E%3Crect width='12' height='12' fill='white'/%3E%3C/clipPath%3E%3C/defs%3E%3C/svg%3E%0A";
|
||||
|
|
|
|||
|
|
@ -70,8 +70,13 @@ $orange: #fd7e14;
|
|||
$teal: #20c997;
|
||||
$cyan: #0dcaf0;
|
||||
|
||||
//Heritage
|
||||
$heritage-blue-primary: #0070D1;
|
||||
$heritage-blue-secondary: #167cac;
|
||||
|
||||
// Darker gray
|
||||
$darker-gray: #525656;
|
||||
$lighter-gray: #9aa1a3;
|
||||
|
||||
// scss-docs-start colors-map
|
||||
$colors: (
|
||||
|
|
@ -114,7 +119,7 @@ $theme-colors: (
|
|||
);
|
||||
|
||||
//Default font color
|
||||
$body-color: $gray-600;
|
||||
$body-color: $darker-gray;
|
||||
|
||||
//Fonts
|
||||
$font-family-sans-serif: Urbanist, Roboto, Arial, sans-serif;
|
||||
|
|
@ -153,6 +158,7 @@ $font-weight-bolder: bolder;
|
|||
$border-radius: 0.25rem;
|
||||
$border-radius-sm: 0.2rem;
|
||||
$border-radius-lg: 0.5rem; //Used for buttons. Can be used for other things, of course.
|
||||
$border-radius-xl: 1.375rem;
|
||||
$border-radius-pill: 50rem;
|
||||
$border-radius-list-button: 1.375rem; // Used for list buttons
|
||||
|
||||
|
|
@ -205,6 +211,11 @@ $alert-bg-scale: -90%;
|
|||
$alert-border-scale: -100%;
|
||||
$alert-color-scale: 40%;
|
||||
|
||||
$alert-yellow-bg: #fef6e8;
|
||||
$alert-yellow-color: #e86421;
|
||||
$alert-red-bg: #fbe9e8;
|
||||
$alert-red-color: $red;
|
||||
|
||||
//Modal animation
|
||||
// This affects all [Bootstrap] modals
|
||||
$modal-fade-transform: translate(0, 100%);
|
||||
|
|
@ -216,9 +227,8 @@ $enable-important-utilities: false;
|
|||
// Letter Spacing
|
||||
$letter-spacing-primary: 0.03em;
|
||||
// Borders
|
||||
$border-input: 1px solid rgba(179, 180, 181);
|
||||
$border-input-focus: 2.5px solid $blue;
|
||||
$border-input: 1px solid $gray-350;
|
||||
$border-input-focus: 2.5px solid $heritage-blue-primary;
|
||||
|
||||
//Heritage
|
||||
$heritage-blue-primary: #0070D1;
|
||||
$heritage-blue-secondary: #167cac;
|
||||
$svg-calendar-error-fill-color: $alert-red-bg;
|
||||
$svg-calendar-error-stroke-color: '%23db0020'; // URL encoded #db0020
|
||||
|
|
@ -1,64 +1,85 @@
|
|||
<template>
|
||||
<div
|
||||
class="alert fade show text-center mb-0 py-2 px-4"
|
||||
class="alert fade show"
|
||||
role="alert"
|
||||
:class="[
|
||||
isDismissible ? 'alert-dismissible' : '',
|
||||
alertClass,
|
||||
cssClassNameForCmsWidget,
|
||||
]">
|
||||
<p class="m-0 fw-bold alert-heading">
|
||||
{{ alertHeadline }}
|
||||
</p>
|
||||
<template
|
||||
v-for="paragraph in splitAlertCopyForParagraphTag"
|
||||
:key="paragraph">
|
||||
<p
|
||||
v-if="!doesCopyContainRouterLink(paragraph) && !doesCopyContainTextLink(paragraph)"
|
||||
class="m-0 text-body small"
|
||||
v-html="paragraph"></p>
|
||||
<p
|
||||
v-else
|
||||
class="m-0 text-body small">
|
||||
<template v-if="doesCopyContainRouterLink(paragraph)">
|
||||
<textBlock
|
||||
:customText="paragraph"
|
||||
class="mb-1"
|
||||
marginTopSizeOverride="0" />
|
||||
</template>
|
||||
<template
|
||||
v-for="copy in splitCopyOnCMSPlaceHolder(paragraph)"
|
||||
v-else
|
||||
:key="copy">
|
||||
<span v-if="doesCopyContainTextLink(copy)">
|
||||
<textLink
|
||||
linkType="text"
|
||||
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
||||
href="#!"
|
||||
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)"
|
||||
@click-event="
|
||||
$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))
|
||||
" />
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
v-html="copy"></span>
|
||||
</template>
|
||||
</p>
|
||||
</template>
|
||||
<button
|
||||
type="button"
|
||||
class="btn-close p-2"
|
||||
data-bs-dismiss="alert"
|
||||
aria-label="Close">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 23.7 23.7"
|
||||
xml:space="preserve">
|
||||
<path
|
||||
d="m23.24 2.7-9.15 9.15L23.24 21a1.581 1.581 0 0 1-1.12 2.7c-.42 0-.82-.16-1.12-.46l-9.15-9.15-9.15 9.15c-.3.3-.7.46-1.12.46A1.581 1.581 0 0 1 .46 21l8.47-8.47.68-.68L.46 2.7c-.62-.62-.62-1.62 0-2.24.62-.62 1.62-.62 2.24 0l8.47 8.47.68.68L21 .46a1.57 1.57 0 0 1 2.23 0c.63.62.63 1.62.01 2.24z" />
|
||||
<div class="alert-header">
|
||||
<svg class="alert-icon" xmlns="http://www.w3.org/2000/svg" width="20" height="21" viewBox="0 0 20 21">
|
||||
<path fill-rule="nonzero" d="M10 .5c5.523 0 10 4.477 10 10s-4.477 10-10 10-10-4.477-10-10S4.477.5 10 .5zm.043 13.6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm.77-9.2h-1.54l-.088.009a.502.502 0 0 0-.299.193.66.66 0 0 0-.125.47l.747 6.806.017.096c.065.249.263.425.495.426l.084-.008c.22-.042.396-.246.427-.51l.793-6.805.004-.102a.651.651 0 0 0-.127-.37.489.489 0 0 0-.388-.205z"/>
|
||||
</svg>
|
||||
</button>
|
||||
<span class="m-0 fw-bold alert-header-text">
|
||||
{{ alertHeadline }}
|
||||
</span>
|
||||
<button
|
||||
v-if="isCollapsible"
|
||||
class="btn-collapse"
|
||||
type="button"
|
||||
@click="toggleCollapse">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="15" height="9" viewBox="0 0 15 9"
|
||||
class="btn-collapse-icon"
|
||||
:class="{ 'rotated': !collapsed }">
|
||||
<path fill-rule="nonzero" d="M7.5 0a.806.806 0 0 0-.593.265L.246 7.455a.957.957 0 0 0 0 1.28.796.796 0 0 0 1.185 0l6.07-6.55 6.068 6.55a.796.796 0 0 0 1.186 0 .957.957 0 0 0 0-1.28L8.093.265A.806.806 0 0 0 7.5 0"/>
|
||||
</svg>
|
||||
</button>
|
||||
<button
|
||||
v-if="isDismissible"
|
||||
type="button"
|
||||
class="btn-close p-2"
|
||||
data-bs-dismiss="alert"
|
||||
aria-label="Close">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 23.7 23.7"
|
||||
xml:space="preserve">
|
||||
<path
|
||||
d="m23.24 2.7-9.15 9.15L23.24 21a1.581 1.581 0 0 1-1.12 2.7c-.42 0-.82-.16-1.12-.46l-9.15-9.15-9.15 9.15c-.3.3-.7.46-1.12.46A1.581 1.581 0 0 1 .46 21l8.47-8.47.68-.68L.46 2.7c-.62-.62-.62-1.62 0-2.24.62-.62 1.62-.62 2.24 0l8.47 8.47.68.68L21 .46a1.57 1.57 0 0 1 2.23 0c.63.62.63 1.62.01 2.24z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div class="alert-body"
|
||||
v-show="alertCopy"
|
||||
:id="collapseId">
|
||||
<template
|
||||
v-for="paragraph in splitAlertCopyForParagraphTag"
|
||||
:key="paragraph">
|
||||
<p
|
||||
v-if="!doesCopyContainRouterLink(paragraph) && !doesCopyContainTextLink(paragraph)"
|
||||
class="m-0 text-body"
|
||||
v-html="paragraph"></p>
|
||||
<p
|
||||
v-else
|
||||
class="m-0 text-body">
|
||||
<template v-if="doesCopyContainRouterLink(paragraph)">
|
||||
<textBlock
|
||||
:customText="paragraph"
|
||||
class="mb-1"
|
||||
marginTopSizeOverride="0" />
|
||||
</template>
|
||||
<template
|
||||
v-for="copy in splitCopyOnCMSPlaceHolder(paragraph)"
|
||||
v-else
|
||||
:key="copy">
|
||||
<span v-if="doesCopyContainTextLink(copy)">
|
||||
<textLink
|
||||
linkType="text"
|
||||
:text="getRouterLinkDisplayTextFromCopy(copy)"
|
||||
href="#!"
|
||||
:data-bs-target="'#' + getRouterLinkRouteFromCopy(copy)"
|
||||
@click-event="
|
||||
$emit('textLinkClicked', getRouterLinkRouteFromCopy(copy))
|
||||
" />
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
v-html="copy"></span>
|
||||
</template>
|
||||
</p>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -74,6 +95,7 @@ import {
|
|||
import applicationConfig from '@/constants/application-config';
|
||||
import textBlock from '@/digital-components/text-block/text-block.vue';
|
||||
import textLink from '@/ux-components/text-link/text-link.vue';
|
||||
import { Collapse } from 'bootstrap';
|
||||
|
||||
export default {
|
||||
// eslint-disable-next-line vue/multi-word-component-names
|
||||
|
|
@ -84,13 +106,14 @@ export default {
|
|||
},
|
||||
props: {
|
||||
isDismissible: Boolean,
|
||||
isCollapsible: Boolean,
|
||||
/*
|
||||
alertClass class names:
|
||||
alert-success (green)
|
||||
alert-danger (red)
|
||||
alert-warning (yellow)
|
||||
alert-info (blue)
|
||||
*/
|
||||
alertClass class names:
|
||||
alert-success (green)
|
||||
alert-danger (red)
|
||||
alert-warning (yellow)
|
||||
alert-info (blue)
|
||||
*/
|
||||
alertClass: String,
|
||||
cmsWidgetName: {
|
||||
type: String,
|
||||
|
|
@ -106,7 +129,14 @@ export default {
|
|||
shouldScrollToOnMount: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
},
|
||||
startCollapsed: Boolean
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
collapsed: this.startCollapsed || false,
|
||||
collapseElement: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
pageQueryString() {
|
||||
|
|
@ -124,10 +154,18 @@ export default {
|
|||
},
|
||||
splitAlertCopyForParagraphTag() {
|
||||
return splitCMSCopyOnParagraphTag(this.alertCopy);
|
||||
}
|
||||
},
|
||||
collapseId() {
|
||||
return this.isCollapsible
|
||||
? `${this.cmsWidgetName}-collapse`
|
||||
: null;
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.ensureAlertIsInViewPort();
|
||||
if (this.isCollapsible) {
|
||||
this.collapseElement = Collapse.getOrCreateInstance(document.getElementById(this.collapseId));
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
doesCopyContainRouterLink,
|
||||
|
|
@ -152,37 +190,83 @@ export default {
|
|||
<= (window.innerHeight - footerHeight
|
||||
|| document.documentElement.clientHeight - footerHeight)
|
||||
);
|
||||
}
|
||||
},
|
||||
toggleCollapse() {
|
||||
this.collapsed = !this.collapsed;
|
||||
if (this.collapsed) {
|
||||
this.collapseElement.hide();
|
||||
} else {
|
||||
this.collapseElement.show();
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.alert {
|
||||
border: 1px solid;
|
||||
padding: 0rem;
|
||||
margin-bottom: 2rem;
|
||||
.alert-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-direction: row;
|
||||
padding: .75rem 1rem .75rem 1rem;
|
||||
font-weight: 600;
|
||||
color: $black;
|
||||
}
|
||||
.alert-icon {
|
||||
min-width: 1rem;
|
||||
max-height: 1rem;
|
||||
}
|
||||
.alert-header-text {
|
||||
flex-grow: 1;
|
||||
padding: 0rem .625rem;
|
||||
}
|
||||
.btn-collapse {
|
||||
display: flex;
|
||||
border: none;
|
||||
background: none;
|
||||
min-width: 1rem;
|
||||
max-height: 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
.btn-collapse-icon {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
transition: transform 0.3s;
|
||||
transform: rotate(180deg);
|
||||
&.rotated {
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
a {
|
||||
text-decoration: none;
|
||||
font-weight: $font-weight-normal;
|
||||
}
|
||||
border-color: transparent;
|
||||
button {
|
||||
display: none;
|
||||
}
|
||||
.btn-close {
|
||||
background: none;
|
||||
opacity: 1;
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
}
|
||||
&.alert-dismissible {
|
||||
button {
|
||||
display: flex;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
}
|
||||
.alert-body {
|
||||
margin: 0 1rem;
|
||||
padding: .5rem 1rem .75rem 1rem;
|
||||
border-top: 1px solid;
|
||||
color: $darker-gray;
|
||||
line-height: 26px;
|
||||
font-weight: 400;
|
||||
}
|
||||
&.alert-info {
|
||||
background-color: $blue-100;
|
||||
.alert-heading {
|
||||
color: $blue-700;
|
||||
border-color: $blue-200;
|
||||
.alert-body {
|
||||
border-top-color: $blue-200;
|
||||
}
|
||||
svg {
|
||||
fill: $blue-700;
|
||||
|
|
@ -191,9 +275,10 @@ export default {
|
|||
}
|
||||
}
|
||||
&.alert-danger {
|
||||
background-color: $red-100;
|
||||
.alert-heading {
|
||||
color: $red-600;
|
||||
background-color: $alert-red-bg;
|
||||
border-color: $alert-red-color;
|
||||
.alert-body {
|
||||
border-top-color: $alert-red-color;
|
||||
}
|
||||
svg {
|
||||
fill: $red-600;
|
||||
|
|
@ -202,20 +287,20 @@ export default {
|
|||
}
|
||||
}
|
||||
&.alert-warning {
|
||||
background-color: $yellow-100;
|
||||
.alert-heading {
|
||||
color: $yellow-600;
|
||||
background-color: $alert-yellow-bg;
|
||||
border-color: $alert-yellow-color;
|
||||
.alert-body {
|
||||
border-top-color: $alert-yellow-color;
|
||||
}
|
||||
svg {
|
||||
fill: $yellow-600;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
fill: $alert-yellow-color;
|
||||
}
|
||||
}
|
||||
&.alert-success {
|
||||
background-color: $green-100;
|
||||
.alert-heading {
|
||||
color: $green-700;
|
||||
border-color: $green-200;
|
||||
.alert-body {
|
||||
border-top-color: $green-200;
|
||||
}
|
||||
svg {
|
||||
fill: $green-700;
|
||||
|
|
@ -223,9 +308,5 @@ export default {
|
|||
height: 1rem;
|
||||
}
|
||||
}
|
||||
& p {
|
||||
font-size: 0.875rem;
|
||||
margin-bottom: 0.25rem !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { getMountOptions } from '@/helpers/unit-test-helper.js';
|
||||
import buttonMain from '@/ux-components/button-main/button-main.vue';
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
import { buttonVariants } from '@/constants/component-variants';
|
||||
import buttonSizes from '@/constants/button-sizes';
|
||||
|
||||
/** @ignore */
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import buttonVariants from '@/constants/button-variants';
|
||||
import { buttonVariants } from '@/constants/component-variants';
|
||||
import buttonSizes from '@/constants/button-sizes';
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,10 @@
|
|||
buttonWrapperClasses="list-group base-input-button list-button no-hover d-flex flex-column w-100 mb-2">
|
||||
<div
|
||||
:aria-label="buttonLabel"
|
||||
class="button-content list-button-content d-flex flex-column justify-content-center py-3 px-4">
|
||||
class="button-content list-button-content d-flex flex-column justify-content-center py-3 px-4"
|
||||
:class="{
|
||||
'has-sub-copy': buttonLabelSubCopy,
|
||||
}">
|
||||
<span
|
||||
class="m-0"
|
||||
:class="textPosition">
|
||||
|
|
@ -85,6 +88,10 @@ $heritage-checked-border-color: #0070d1;
|
|||
background: $heritage-checked-background-color;
|
||||
border-color: $heritage-checked-border-color;
|
||||
box-shadow: 0 0 0 1px $blue;
|
||||
&:not(.has-sub-copy) {
|
||||
font-weight: 500;
|
||||
color: $black;
|
||||
}
|
||||
}
|
||||
&:checked + .list-button-content span:nth-child(2) {
|
||||
font-weight: 400;
|
||||
|
|
@ -104,10 +111,15 @@ $heritage-checked-border-color: #0070d1;
|
|||
width: 100%;
|
||||
outline: none;
|
||||
|
||||
&:not(.has-sub-copy) {
|
||||
font-weight: 400;
|
||||
color: $darker-gray;
|
||||
}
|
||||
|
||||
span {
|
||||
&.small {
|
||||
color: $darker-gray;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
@ -62,7 +62,7 @@ export default {
|
|||
|
||||
<style lang="scss" scoped>
|
||||
a {
|
||||
color: #0070d1;
|
||||
color: $heritage-blue-primary;
|
||||
text-decoration: none;
|
||||
line-height: 1.56;
|
||||
padding: 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue