feat: first two questions of Skills Builder
This commit is contained in:
326
package-lock.json
generated
326
package-lock.json
generated
@@ -30,6 +30,7 @@
|
||||
"react": "16.14.0",
|
||||
"react-dom": "16.14.0",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-instantsearch-hooks-web": "^6.40.1",
|
||||
"react-redux": "7.2.9",
|
||||
"react-router": "5.3.4",
|
||||
"react-router-dom": "5.3.4",
|
||||
@@ -129,6 +130,11 @@
|
||||
"@algolia/transporter": "4.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/events": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz",
|
||||
"integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ=="
|
||||
},
|
||||
"node_modules/@algolia/logger-common": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.6.0.tgz",
|
||||
@@ -173,6 +179,20 @@
|
||||
"@algolia/requester-common": "4.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/ui-components-highlight-vdom": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/ui-components-highlight-vdom/-/ui-components-highlight-vdom-1.2.1.tgz",
|
||||
"integrity": "sha512-IlYgIaCUEkz9ezNbwugwKv991oOHhveyq6nzL0F1jDzg1p3q5Yj/vO4KpNG910r2dwGCG3nEm5GtChcLnarhFA==",
|
||||
"dependencies": {
|
||||
"@algolia/ui-components-shared": "1.2.1",
|
||||
"@babel/runtime": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@algolia/ui-components-shared": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/ui-components-shared/-/ui-components-shared-1.2.1.tgz",
|
||||
"integrity": "sha512-a7mYHf/GVQfhAx/HRiMveKkFvHspQv/REdG+C/FIOosiSmNZxX7QebDwJkrGSmDWdXO12D0Qv1xn3AytFcEDlQ=="
|
||||
},
|
||||
"node_modules/@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
||||
@@ -4496,6 +4516,11 @@
|
||||
"version": "0.3.3",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@types/dom-speech-recognition": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz",
|
||||
"integrity": "sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw=="
|
||||
},
|
||||
"node_modules/@types/eslint": {
|
||||
"version": "8.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz",
|
||||
@@ -4564,6 +4589,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/google.maps": {
|
||||
"version": "3.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.52.0.tgz",
|
||||
"integrity": "sha512-cIwkgSBUOCerEwEpAahg1SxUqqGV+D786TkVWrcZZyPvuCozmXFtzQcpOzvUXBtTUqDzEbCDGlAXDfDSYFXFIw=="
|
||||
},
|
||||
"node_modules/@types/graceful-fs": {
|
||||
"version": "4.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
|
||||
@@ -4573,6 +4603,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/hogan.js": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/hogan.js/-/hogan.js-3.0.1.tgz",
|
||||
"integrity": "sha512-D03i/2OY7kGyMq9wdQ7oD8roE49z/ZCZThe/nbahtvuqCNZY9T2MfedOWyeBdbEpY2W8Gnh/dyJLdFtUCOkYbg=="
|
||||
},
|
||||
"node_modules/@types/hoist-non-react-statics": {
|
||||
"version": "3.3.1",
|
||||
"license": "MIT",
|
||||
@@ -4681,8 +4716,7 @@
|
||||
"node_modules/@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
|
||||
},
|
||||
"node_modules/@types/range-parser": {
|
||||
"version": "1.2.4",
|
||||
@@ -5071,6 +5105,11 @@
|
||||
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
@@ -5298,6 +5337,17 @@
|
||||
"@algolia/transporter": "4.6.0"
|
||||
}
|
||||
},
|
||||
"node_modules/algoliasearch-helper": {
|
||||
"version": "3.11.3",
|
||||
"resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.11.3.tgz",
|
||||
"integrity": "sha512-TbaEvLwiuGygHQIB8y+OsJKQQ40+JKUua5B91X66tMUHyyhbNHvqyr0lqd3wCoyKx7WybyQrC0WJvzoIeh24Aw==",
|
||||
"dependencies": {
|
||||
"@algolia/events": "^4.0.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"algoliasearch": ">= 3.1 < 6"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||
@@ -10334,6 +10384,27 @@
|
||||
"value-equal": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/hogan.js": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz",
|
||||
"integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==",
|
||||
"dependencies": {
|
||||
"mkdirp": "0.3.0",
|
||||
"nopt": "1.0.10"
|
||||
},
|
||||
"bin": {
|
||||
"hulk": "bin/hulk"
|
||||
}
|
||||
},
|
||||
"node_modules/hogan.js/node_modules/mkdirp": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz",
|
||||
"integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==",
|
||||
"deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)",
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"license": "BSD-3-Clause",
|
||||
@@ -10400,6 +10471,11 @@
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/htm": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz",
|
||||
"integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ=="
|
||||
},
|
||||
"node_modules/html-element-map": {
|
||||
"version": "1.3.1",
|
||||
"dev": true,
|
||||
@@ -10885,6 +10961,40 @@
|
||||
"dev": true,
|
||||
"license": "ISC"
|
||||
},
|
||||
"node_modules/instantsearch.js": {
|
||||
"version": "4.51.1",
|
||||
"resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-4.51.1.tgz",
|
||||
"integrity": "sha512-l4nETzassgSMBqOhNxntNH2MGG0KvFagwVwnXFis9P06nlspAyOdFLCQ0HA5wnlRDDev2WAZg9xRcTPCTLrwZw==",
|
||||
"dependencies": {
|
||||
"@algolia/events": "^4.0.1",
|
||||
"@algolia/ui-components-highlight-vdom": "^1.2.1",
|
||||
"@algolia/ui-components-shared": "^1.2.1",
|
||||
"@types/dom-speech-recognition": "^0.0.1",
|
||||
"@types/google.maps": "^3.45.3",
|
||||
"@types/hogan.js": "^3.0.0",
|
||||
"@types/qs": "^6.5.3",
|
||||
"algoliasearch-helper": "^3.11.3",
|
||||
"hogan.js": "^3.0.2",
|
||||
"htm": "^3.0.0",
|
||||
"preact": "^10.10.0",
|
||||
"qs": "^6.5.1 < 6.10",
|
||||
"search-insights": "^2.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"algoliasearch": ">= 3.1 < 6"
|
||||
}
|
||||
},
|
||||
"node_modules/instantsearch.js/node_modules/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz",
|
||||
"integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
},
|
||||
"node_modules/internal-slot": {
|
||||
"version": "1.0.3",
|
||||
"dev": true,
|
||||
@@ -13524,6 +13634,20 @@
|
||||
"integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/nopt": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
|
||||
"integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
|
||||
"dependencies": {
|
||||
"abbrev": "1"
|
||||
},
|
||||
"bin": {
|
||||
"nopt": "bin/nopt.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/normalize-package-data": {
|
||||
"version": "3.0.3",
|
||||
"dev": true,
|
||||
@@ -14920,6 +15044,15 @@
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/preact": {
|
||||
"version": "10.12.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz",
|
||||
"integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg==",
|
||||
"funding": {
|
||||
"type": "opencollective",
|
||||
"url": "https://opencollective.com/preact"
|
||||
}
|
||||
},
|
||||
"node_modules/prebuild-install": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
|
||||
@@ -15502,6 +15635,36 @@
|
||||
"react": ">=16.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/react-instantsearch-hooks": {
|
||||
"version": "6.40.1",
|
||||
"resolved": "https://registry.npmjs.org/react-instantsearch-hooks/-/react-instantsearch-hooks-6.40.1.tgz",
|
||||
"integrity": "sha512-Nqbmencg5816UVDkWUFpGyurAhp8WUBQgHiYj/bTnYQ7KuwXbbxIppIwexZqzXG8Q3DKVBWZw4PnmJiStLK2CA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"algoliasearch-helper": "^3.11.3",
|
||||
"instantsearch.js": "4.51.1",
|
||||
"use-sync-external-store": "^1.0.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"algoliasearch": ">= 3.1 < 5",
|
||||
"react": ">= 16.8.0 < 19"
|
||||
}
|
||||
},
|
||||
"node_modules/react-instantsearch-hooks-web": {
|
||||
"version": "6.40.1",
|
||||
"resolved": "https://registry.npmjs.org/react-instantsearch-hooks-web/-/react-instantsearch-hooks-web-6.40.1.tgz",
|
||||
"integrity": "sha512-MbsS1nhyZWPJjSVRzkDVmb0TM4L2kjHANsr0e1NDwkVWicP8LtXdX6UINDnekMKVnk1OmoF10NAJt4LmcSOqaA==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"instantsearch.js": "4.51.1",
|
||||
"react-instantsearch-hooks": "6.40.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"algoliasearch": ">= 3.1 < 5",
|
||||
"react": ">= 16.8.0 < 19",
|
||||
"react-dom": ">= 16.8.0 < 19"
|
||||
}
|
||||
},
|
||||
"node_modules/react-intl": {
|
||||
"version": "5.25.1",
|
||||
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.25.1.tgz",
|
||||
@@ -16951,6 +17114,14 @@
|
||||
"url": "https://opencollective.com/webpack"
|
||||
}
|
||||
},
|
||||
"node_modules/search-insights": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.3.0.tgz",
|
||||
"integrity": "sha512-0v/TTO4fbd6I91sFBK/e2zNfD0f51A+fMoYNkMplmR77NpThUye/7gIxNoJ3LejKpZH6Z2KNBIpxxFmDKj10Yw==",
|
||||
"engines": {
|
||||
"node": ">=8.16.0"
|
||||
}
|
||||
},
|
||||
"node_modules/select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
@@ -19189,6 +19360,14 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||
"peerDependencies": {
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"dev": true,
|
||||
@@ -20173,6 +20352,11 @@
|
||||
"@algolia/transporter": "4.6.0"
|
||||
}
|
||||
},
|
||||
"@algolia/events": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/events/-/events-4.0.1.tgz",
|
||||
"integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ=="
|
||||
},
|
||||
"@algolia/logger-common": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.6.0.tgz",
|
||||
@@ -20217,6 +20401,20 @@
|
||||
"@algolia/requester-common": "4.6.0"
|
||||
}
|
||||
},
|
||||
"@algolia/ui-components-highlight-vdom": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/ui-components-highlight-vdom/-/ui-components-highlight-vdom-1.2.1.tgz",
|
||||
"integrity": "sha512-IlYgIaCUEkz9ezNbwugwKv991oOHhveyq6nzL0F1jDzg1p3q5Yj/vO4KpNG910r2dwGCG3nEm5GtChcLnarhFA==",
|
||||
"requires": {
|
||||
"@algolia/ui-components-shared": "1.2.1",
|
||||
"@babel/runtime": "^7.0.0"
|
||||
}
|
||||
},
|
||||
"@algolia/ui-components-shared": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@algolia/ui-components-shared/-/ui-components-shared-1.2.1.tgz",
|
||||
"integrity": "sha512-a7mYHf/GVQfhAx/HRiMveKkFvHspQv/REdG+C/FIOosiSmNZxX7QebDwJkrGSmDWdXO12D0Qv1xn3AytFcEDlQ=="
|
||||
},
|
||||
"@ampproject/remapping": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz",
|
||||
@@ -23399,6 +23597,11 @@
|
||||
"@types/cookie": {
|
||||
"version": "0.3.3"
|
||||
},
|
||||
"@types/dom-speech-recognition": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/dom-speech-recognition/-/dom-speech-recognition-0.0.1.tgz",
|
||||
"integrity": "sha512-udCxb8DvjcDKfk1WTBzDsxFbLgYxmQGKrE/ricoMqHRNjSlSUCcamVTA5lIQqzY10mY5qCY0QDwBfFEwhfoDPw=="
|
||||
},
|
||||
"@types/eslint": {
|
||||
"version": "8.4.10",
|
||||
"resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.4.10.tgz",
|
||||
@@ -23467,6 +23670,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/google.maps": {
|
||||
"version": "3.52.0",
|
||||
"resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.52.0.tgz",
|
||||
"integrity": "sha512-cIwkgSBUOCerEwEpAahg1SxUqqGV+D786TkVWrcZZyPvuCozmXFtzQcpOzvUXBtTUqDzEbCDGlAXDfDSYFXFIw=="
|
||||
},
|
||||
"@types/graceful-fs": {
|
||||
"version": "4.1.6",
|
||||
"resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
|
||||
@@ -23476,6 +23684,11 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/hogan.js": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/hogan.js/-/hogan.js-3.0.1.tgz",
|
||||
"integrity": "sha512-D03i/2OY7kGyMq9wdQ7oD8roE49z/ZCZThe/nbahtvuqCNZY9T2MfedOWyeBdbEpY2W8Gnh/dyJLdFtUCOkYbg=="
|
||||
},
|
||||
"@types/hoist-non-react-statics": {
|
||||
"version": "3.3.1",
|
||||
"requires": {
|
||||
@@ -23577,8 +23790,7 @@
|
||||
"@types/qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
|
||||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
|
||||
"dev": true
|
||||
"integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw=="
|
||||
},
|
||||
"@types/range-parser": {
|
||||
"version": "1.2.4",
|
||||
@@ -23945,6 +24157,11 @@
|
||||
"integrity": "sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==",
|
||||
"dev": true
|
||||
},
|
||||
"abbrev": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
|
||||
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
|
||||
},
|
||||
"accepts": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
@@ -24116,6 +24333,14 @@
|
||||
"@algolia/transporter": "4.6.0"
|
||||
}
|
||||
},
|
||||
"algoliasearch-helper": {
|
||||
"version": "3.11.3",
|
||||
"resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.11.3.tgz",
|
||||
"integrity": "sha512-TbaEvLwiuGygHQIB8y+OsJKQQ40+JKUua5B91X66tMUHyyhbNHvqyr0lqd3wCoyKx7WybyQrC0WJvzoIeh24Aw==",
|
||||
"requires": {
|
||||
"@algolia/events": "^4.0.1"
|
||||
}
|
||||
},
|
||||
"ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
|
||||
@@ -27838,6 +28063,22 @@
|
||||
"value-equal": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"hogan.js": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz",
|
||||
"integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==",
|
||||
"requires": {
|
||||
"mkdirp": "0.3.0",
|
||||
"nopt": "1.0.10"
|
||||
},
|
||||
"dependencies": {
|
||||
"mkdirp": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz",
|
||||
"integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"hoist-non-react-statics": {
|
||||
"version": "3.3.2",
|
||||
"requires": {
|
||||
@@ -27901,6 +28142,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"htm": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/htm/-/htm-3.1.1.tgz",
|
||||
"integrity": "sha512-983Vyg8NwUE7JkZ6NmOqpCZ+sh1bKv2iYTlUkzlWmA5JD2acKoxd4KVxbMmxX/85mtfdnDmTFoNKcg5DGAvxNQ=="
|
||||
},
|
||||
"html-element-map": {
|
||||
"version": "1.3.1",
|
||||
"dev": true,
|
||||
@@ -28221,6 +28467,33 @@
|
||||
"version": "1.3.8",
|
||||
"dev": true
|
||||
},
|
||||
"instantsearch.js": {
|
||||
"version": "4.51.1",
|
||||
"resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-4.51.1.tgz",
|
||||
"integrity": "sha512-l4nETzassgSMBqOhNxntNH2MGG0KvFagwVwnXFis9P06nlspAyOdFLCQ0HA5wnlRDDev2WAZg9xRcTPCTLrwZw==",
|
||||
"requires": {
|
||||
"@algolia/events": "^4.0.1",
|
||||
"@algolia/ui-components-highlight-vdom": "^1.2.1",
|
||||
"@algolia/ui-components-shared": "^1.2.1",
|
||||
"@types/dom-speech-recognition": "^0.0.1",
|
||||
"@types/google.maps": "^3.45.3",
|
||||
"@types/hogan.js": "^3.0.0",
|
||||
"@types/qs": "^6.5.3",
|
||||
"algoliasearch-helper": "^3.11.3",
|
||||
"hogan.js": "^3.0.2",
|
||||
"htm": "^3.0.0",
|
||||
"preact": "^10.10.0",
|
||||
"qs": "^6.5.1 < 6.10",
|
||||
"search-insights": "^2.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"qs": {
|
||||
"version": "6.9.7",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.9.7.tgz",
|
||||
"integrity": "sha512-IhMFgUmuNpyRfxA90umL7ByLlgRXu6tIfKPpF5TmcfRLlLCckfP/g3IQmju6jjpu+Hh8rA+2p6A27ZSPOOHdKw=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"internal-slot": {
|
||||
"version": "1.0.3",
|
||||
"dev": true,
|
||||
@@ -30206,6 +30479,14 @@
|
||||
"integrity": "sha512-dFSmB8fFHEH/s81Xi+Y/15DQY6VHW81nXRj86EMSL3lmuTmK1e+aT4wrFCkTbm+gSwkw4KpX+rT/pMM2c1mF+A==",
|
||||
"dev": true
|
||||
},
|
||||
"nopt": {
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz",
|
||||
"integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==",
|
||||
"requires": {
|
||||
"abbrev": "1"
|
||||
}
|
||||
},
|
||||
"normalize-package-data": {
|
||||
"version": "3.0.3",
|
||||
"dev": true,
|
||||
@@ -31136,6 +31417,11 @@
|
||||
"integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==",
|
||||
"dev": true
|
||||
},
|
||||
"preact": {
|
||||
"version": "10.12.1",
|
||||
"resolved": "https://registry.npmjs.org/preact/-/preact-10.12.1.tgz",
|
||||
"integrity": "sha512-l8386ixSsBdbreOAkqtrwqHwdvR35ID8c3rKPa8lCWuO86dBi32QWHV4vfsZK1utLLFMvw+Z5Ad4XLkZzchscg=="
|
||||
},
|
||||
"prebuild-install": {
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz",
|
||||
@@ -31566,6 +31852,27 @@
|
||||
"react-side-effect": "^2.1.0"
|
||||
}
|
||||
},
|
||||
"react-instantsearch-hooks": {
|
||||
"version": "6.40.1",
|
||||
"resolved": "https://registry.npmjs.org/react-instantsearch-hooks/-/react-instantsearch-hooks-6.40.1.tgz",
|
||||
"integrity": "sha512-Nqbmencg5816UVDkWUFpGyurAhp8WUBQgHiYj/bTnYQ7KuwXbbxIppIwexZqzXG8Q3DKVBWZw4PnmJiStLK2CA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"algoliasearch-helper": "^3.11.3",
|
||||
"instantsearch.js": "4.51.1",
|
||||
"use-sync-external-store": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"react-instantsearch-hooks-web": {
|
||||
"version": "6.40.1",
|
||||
"resolved": "https://registry.npmjs.org/react-instantsearch-hooks-web/-/react-instantsearch-hooks-web-6.40.1.tgz",
|
||||
"integrity": "sha512-MbsS1nhyZWPJjSVRzkDVmb0TM4L2kjHANsr0e1NDwkVWicP8LtXdX6UINDnekMKVnk1OmoF10NAJt4LmcSOqaA==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.1.2",
|
||||
"instantsearch.js": "4.51.1",
|
||||
"react-instantsearch-hooks": "6.40.1"
|
||||
}
|
||||
},
|
||||
"react-intl": {
|
||||
"version": "5.25.1",
|
||||
"resolved": "https://registry.npmjs.org/react-intl/-/react-intl-5.25.1.tgz",
|
||||
@@ -32592,6 +32899,11 @@
|
||||
"ajv-keywords": "^3.5.2"
|
||||
}
|
||||
},
|
||||
"search-insights": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.3.0.tgz",
|
||||
"integrity": "sha512-0v/TTO4fbd6I91sFBK/e2zNfD0f51A+fMoYNkMplmR77NpThUye/7gIxNoJ3LejKpZH6Z2KNBIpxxFmDKj10Yw=="
|
||||
},
|
||||
"select-hose": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
|
||||
@@ -34297,6 +34609,12 @@
|
||||
"tslib": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"use-sync-external-store": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
|
||||
"integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
|
||||
"requires": {}
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"dev": true
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
"react": "16.14.0",
|
||||
"react-dom": "16.14.0",
|
||||
"react-helmet": "6.1.0",
|
||||
"react-instantsearch-hooks-web": "^6.40.1",
|
||||
"react-redux": "7.2.9",
|
||||
"react-router": "5.3.4",
|
||||
"react-router-dom": "5.3.4",
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Actions for Skills Context
|
||||
export const SET_GOAL = 'SET_GOAL';
|
||||
export const SET_CURRENT_JOB_TITLE = 'SET_CURRENT_JOB_TITLE';
|
||||
export const ADD_CAREER_INTEREST = 'ADD_CAREER_INTEREST';
|
||||
export const REMOVE_CAREER_INTEREEST = 'REMOVE_CAREER_INTEREEST';
|
||||
|
||||
// Stepper keys
|
||||
export const STEP1 = 'select-your-preferences';
|
||||
export const STEP2 = 'review-your-results';
|
||||
|
||||
@@ -1,12 +1,24 @@
|
||||
import React, { createContext, useReducer, useMemo } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import reducer, { skillsInitialState } from '../data/reducer';
|
||||
import { useAlgoliaSearch } from '../utils/search';
|
||||
|
||||
export const SkillsBuilderContext = createContext();
|
||||
|
||||
export const SkillsBuilderProvider = ({ children }) => {
|
||||
const [state, dispatch] = useReducer(reducer, skillsInitialState);
|
||||
const value = useMemo(() => ([state, dispatch]), [state]);
|
||||
|
||||
const [searchClient, productSearchIndex, jobSearchIndex] = useAlgoliaSearch();
|
||||
|
||||
const value = useMemo(() => ({
|
||||
state,
|
||||
dispatch,
|
||||
algolia: {
|
||||
searchClient,
|
||||
productSearchIndex,
|
||||
jobSearchIndex,
|
||||
},
|
||||
}), [state, searchClient, productSearchIndex, jobSearchIndex]);
|
||||
|
||||
return (
|
||||
<SkillsBuilderContext.Provider value={value}>
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import React, { useContext } from 'react';
|
||||
import {
|
||||
Button,
|
||||
} from '@edx/paragon';
|
||||
import {
|
||||
setGoal,
|
||||
setCurrentJobTitle,
|
||||
addCareerInterest,
|
||||
removeCareerInterest,
|
||||
} from '../data/actions';
|
||||
import { SkillsBuilderContext } from '../skills-builder-context';
|
||||
import { useAlgoliaSearch } from '../utils/search';
|
||||
|
||||
const SelectPreferences = () => {
|
||||
// TODO: Temporarily disable the no-unused-vars check, we'll see these later
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const [algoliaClient, productSearchIndex, jobSearchIndex] = useAlgoliaSearch();
|
||||
const [{ currentGoal, currentJobTitle, careerInterests }, dispatch] = useContext(SkillsBuilderContext);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="p-4">
|
||||
<h3>Render Question 1</h3>
|
||||
<Button onClick={() => dispatch(setGoal('learn new things'))}>
|
||||
Answer question 1
|
||||
</Button>
|
||||
<p>Goal: {currentGoal}</p>
|
||||
</div>
|
||||
|
||||
{currentGoal && (
|
||||
<div className="p-4">
|
||||
<h3>Render question 2</h3>
|
||||
<Button onClick={() => dispatch(setCurrentJobTitle('Software Engineer'))}>
|
||||
Answer question 2
|
||||
</Button>
|
||||
<p>Current Job Title: {currentJobTitle}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{currentJobTitle && (
|
||||
<div className="p-4">
|
||||
<h3>Render Question 3</h3>
|
||||
<Button
|
||||
onClick={() => dispatch(addCareerInterest(`Joining the circus ${Math.random().toFixed(2)}`))}
|
||||
disabled={careerInterests.length >= 3}
|
||||
>
|
||||
Answer question 3
|
||||
</Button>
|
||||
<p>
|
||||
Career Interests (click to remove):
|
||||
{careerInterests.map(interest => (
|
||||
<Button onClick={() => dispatch(removeCareerInterest(interest))}>
|
||||
{interest}
|
||||
</Button>
|
||||
))}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectPreferences;
|
||||
@@ -1,27 +1,25 @@
|
||||
import React, { useState, useContext } from 'react';
|
||||
import {
|
||||
Button,
|
||||
Container,
|
||||
Stepper,
|
||||
ModalDialog,
|
||||
Button, Container, Stepper, ModalDialog,
|
||||
} from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { useHistory } from 'react-router';
|
||||
import {
|
||||
STEP1,
|
||||
STEP2,
|
||||
STEP1, STEP2,
|
||||
} from '../data/constants';
|
||||
import messages from './messages';
|
||||
|
||||
import { SkillsBuilderContext } from '../skills-builder-context';
|
||||
import { SkillsBuilderHeader } from '../skills-builder-header';
|
||||
import SelectPreferences from './SelectPreferences';
|
||||
import ViewResults from './ViewResults';
|
||||
import { SelectPreferences } from './select-preferences';
|
||||
import ViewResults from './view-results/ViewResults';
|
||||
|
||||
import headerImage from '../images/headerImage.png';
|
||||
|
||||
const SkillsBuilderModal = () => {
|
||||
const [{ careerInterests }] = useContext(SkillsBuilderContext);
|
||||
const intl = useIntl();
|
||||
const { state } = useContext(SkillsBuilderContext);
|
||||
const { careerInterests } = state;
|
||||
const [currentStep, setCurrentStep] = useState(STEP1);
|
||||
|
||||
const history = useHistory();
|
||||
@@ -48,13 +46,15 @@ const SkillsBuilderModal = () => {
|
||||
</ModalDialog.Hero.Content>
|
||||
</ModalDialog.Hero>
|
||||
|
||||
<Stepper.Header />
|
||||
|
||||
<ModalDialog.Body>
|
||||
<Container size="lg">
|
||||
<Stepper.Step eventKey={STEP1} title="Select preferences">
|
||||
<Container size="md">
|
||||
<Stepper.Step eventKey={STEP1} title={intl.formatMessage(messages.selectPreferences)}>
|
||||
<SelectPreferences />
|
||||
</Stepper.Step>
|
||||
|
||||
<Stepper.Step eventKey={STEP2} title="Review results">
|
||||
<Stepper.Step eventKey={STEP2} title={intl.formatMessage(messages.reviewResults)}>
|
||||
<ViewResults />
|
||||
</Stepper.Step>
|
||||
</Container>
|
||||
@@ -62,7 +62,7 @@ const SkillsBuilderModal = () => {
|
||||
|
||||
<ModalDialog.Footer>
|
||||
<Stepper.ActionRow eventKey={STEP1}>
|
||||
<Button variant="outline-primary">
|
||||
<Button variant="outline-primary" onClick={onCloseHandle}>
|
||||
<FormattedMessage {...messages.goBackButton} />
|
||||
</Button>
|
||||
<Stepper.ActionRow.Spacer />
|
||||
|
||||
@@ -17,6 +17,16 @@ const messages = defineMessages({
|
||||
defaultMessage: 'Exit',
|
||||
description: 'Button that exits the Skills Builder.',
|
||||
},
|
||||
selectPreferences: {
|
||||
id: 'select.preferences',
|
||||
defaultMessage: 'Select preferences',
|
||||
description: 'The first step of the Skills Builder for selecting a goal, a current job/occupation, and career interests',
|
||||
},
|
||||
reviewResults: {
|
||||
id: 'review.results',
|
||||
defaultMessage: 'Review results',
|
||||
description: 'The second step of the Skills Builder for rendering results from learner input',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import React from 'react';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import messages from './messages';
|
||||
|
||||
const CareerInterestSelect = () => (
|
||||
<div>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.careerInterestPrompt} />
|
||||
</h4>
|
||||
<p>
|
||||
JobTitleAutosuggest component can be reused here
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
export default CareerInterestSelect;
|
||||
@@ -0,0 +1,38 @@
|
||||
import React, { useContext } from 'react';
|
||||
import {
|
||||
Form,
|
||||
Stack,
|
||||
} from '@edx/paragon';
|
||||
import { FormattedMessage, useIntl } from '@edx/frontend-platform/i18n';
|
||||
import { setGoal } from '../../data/actions';
|
||||
import { SkillsBuilderContext } from '../../skills-builder-context';
|
||||
import messages from './messages';
|
||||
|
||||
const GoalDropdown = () => {
|
||||
const intl = useIntl();
|
||||
const { state, dispatch } = useContext(SkillsBuilderContext);
|
||||
const { currentGoal } = state;
|
||||
|
||||
return (
|
||||
<Stack gap={2}>
|
||||
<h4><FormattedMessage {...messages.learningGoalPrompt} /></h4>
|
||||
<Form.Group>
|
||||
<Form.Control
|
||||
as="select"
|
||||
value={currentGoal}
|
||||
onChange={(e) => dispatch(setGoal(e.target.value))}
|
||||
>
|
||||
<option value="">{intl.formatMessage(messages.selectLearningGoal)}</option>
|
||||
<option>{intl.formatMessage(messages.learningGoalStartCareer)}</option>
|
||||
<option>{intl.formatMessage(messages.learningGoalAdvanceCareer)}</option>
|
||||
<option>{intl.formatMessage(messages.learningGoalChangeCareer)}</option>
|
||||
<option>{intl.formatMessage(messages.learningGoalSomethingNew)}</option>
|
||||
<option>{intl.formatMessage(messages.learningGoalSomethingElse)}</option>
|
||||
</Form.Control>
|
||||
</Form.Group>
|
||||
</Stack>
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
export default GoalDropdown;
|
||||
@@ -0,0 +1,39 @@
|
||||
import React, { useState } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
Form,
|
||||
} from '@edx/paragon';
|
||||
import { useHits, useSearchBox } from 'react-instantsearch-hooks-web';
|
||||
|
||||
const JobTitleInstantSearch = (props) => {
|
||||
const { refine } = useSearchBox(props);
|
||||
const { hits } = useHits(props);
|
||||
|
||||
const [jobInput, setJobInput] = useState('');
|
||||
|
||||
const handleAutosuggestChange = (value) => {
|
||||
setJobInput(value);
|
||||
refine(value);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form.Autosuggest
|
||||
value={jobInput}
|
||||
onChange={handleAutosuggestChange}
|
||||
name="job-title-suggest"
|
||||
onSelected={props.onSelected}
|
||||
>
|
||||
{hits.map(job => (
|
||||
<Form.AutosuggestOption key={job.id}>
|
||||
{job.name}
|
||||
</Form.AutosuggestOption>
|
||||
))}
|
||||
</Form.Autosuggest>
|
||||
);
|
||||
};
|
||||
|
||||
JobTitleInstantSearch.propTypes = {
|
||||
onSelected: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
export default JobTitleInstantSearch;
|
||||
@@ -0,0 +1,46 @@
|
||||
import React, { useContext } from 'react';
|
||||
import {
|
||||
Form, Stack,
|
||||
} from '@edx/paragon';
|
||||
import { getConfig } from '@edx/frontend-platform';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import { InstantSearch } from 'react-instantsearch-hooks-web';
|
||||
import { setCurrentJobTitle } from '../../data/actions';
|
||||
import { SkillsBuilderContext } from '../../skills-builder-context';
|
||||
import JobTitleInstantSearch from './JobTitleInstantSearch';
|
||||
import messages from './messages';
|
||||
|
||||
const JobTitleSelect = () => {
|
||||
const { dispatch, algolia } = useContext(SkillsBuilderContext);
|
||||
const { searchClient } = algolia;
|
||||
|
||||
// Below implementation sets the job title to "student" or "looking_for_work" — this overwrites any previous selection
|
||||
// This will need to be revisited when we decide what to do with this data
|
||||
const handleCheckboxChange = (e) => dispatch(setCurrentJobTitle(e.target.value));
|
||||
|
||||
return (
|
||||
<Stack gap={2}>
|
||||
<h4>
|
||||
<FormattedMessage {...messages.jobTitlePrompt} />
|
||||
</h4>
|
||||
<InstantSearch searchClient={searchClient} indexName={getConfig().ALGOLIA_JOBS_INDEX_NAME}>
|
||||
<JobTitleInstantSearch onSelected={(value) => dispatch(setCurrentJobTitle(value))} />
|
||||
</InstantSearch>
|
||||
<Form.Group>
|
||||
<Form.CheckboxSet
|
||||
name="other-occupations"
|
||||
onChange={handleCheckboxChange}
|
||||
>
|
||||
<Form.Checkbox value="student">
|
||||
<FormattedMessage {...messages.studentCheckboxPrompt} />
|
||||
</Form.Checkbox>
|
||||
<Form.Checkbox value="looking_for_work">
|
||||
<FormattedMessage {...messages.currentlyLookingCheckboxPrompt} />
|
||||
</Form.Checkbox>
|
||||
</Form.CheckboxSet>
|
||||
</Form.Group>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default JobTitleSelect;
|
||||
@@ -0,0 +1,36 @@
|
||||
import React, { useContext } from 'react';
|
||||
import {
|
||||
Stack,
|
||||
} from '@edx/paragon';
|
||||
import { FormattedMessage } from '@edx/frontend-platform/i18n';
|
||||
import { SkillsBuilderContext } from '../../skills-builder-context';
|
||||
|
||||
import GoalSelect from './GoalSelect';
|
||||
import JobTitleSelect from './JobTitleSelect';
|
||||
import CareerInterestSelect from './CareerInterestSelect';
|
||||
import messages from './messages';
|
||||
|
||||
const SelectPreferences = () => {
|
||||
const { state } = useContext(SkillsBuilderContext);
|
||||
const { currentGoal, currentJobTitle } = state;
|
||||
|
||||
return (
|
||||
<Stack gap={5}>
|
||||
<p className="lead">
|
||||
<FormattedMessage {...messages.skillsBuilderDescription} />
|
||||
</p>
|
||||
|
||||
<GoalSelect />
|
||||
|
||||
{currentGoal && (
|
||||
<JobTitleSelect />
|
||||
)}
|
||||
|
||||
{currentJobTitle && (
|
||||
<CareerInterestSelect />
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
export default SelectPreferences;
|
||||
@@ -0,0 +1,2 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export { default as SelectPreferences } from './SelectPreferences';
|
||||
@@ -0,0 +1,66 @@
|
||||
import { defineMessages } from '@edx/frontend-platform/i18n';
|
||||
|
||||
const messages = defineMessages({
|
||||
skillsBuilderDescription: {
|
||||
id: 'skills.builder.description',
|
||||
defaultMessage: 'Find the right courses and programs that help you reach your goals.',
|
||||
description: 'Description of what the Skills Builder seeks to accomplish',
|
||||
},
|
||||
learningGoalPrompt: {
|
||||
id: 'learning.goal.prompt',
|
||||
defaultMessage: 'First, tell us what you want to achieve',
|
||||
description: 'Prompts the user to select their current goal.',
|
||||
},
|
||||
selectLearningGoal: {
|
||||
id: 'select.learning.goal',
|
||||
defaultMessage: 'Select a goal',
|
||||
description: 'Placeholder text for the goal selection component.',
|
||||
},
|
||||
learningGoalStartCareer: {
|
||||
id: 'learning.goal.start_career',
|
||||
defaultMessage: 'I want to start my career',
|
||||
description: 'Selected by user if their goal is to start their career.',
|
||||
},
|
||||
learningGoalAdvanceCareer: {
|
||||
id: 'learning.goal.advance_career',
|
||||
defaultMessage: 'I want to advance my career',
|
||||
description: 'Selected by user if their goal is to advance their career.',
|
||||
},
|
||||
learningGoalChangeCareer: {
|
||||
id: 'learning.goal.change_career',
|
||||
defaultMessage: 'I want to change careers',
|
||||
description: 'Selected by user if their goal is to change careers.',
|
||||
},
|
||||
learningGoalSomethingNew: {
|
||||
id: 'learning.goal.something.new',
|
||||
defaultMessage: 'I want to learn something new',
|
||||
description: 'Selected by user if their goal is to learn something new.',
|
||||
},
|
||||
learningGoalSomethingElse: {
|
||||
id: 'learning.goal.something.else',
|
||||
defaultMessage: 'Something else',
|
||||
description: 'Selected by user if their goal is not described by the other choices.',
|
||||
},
|
||||
jobTitlePrompt: {
|
||||
id: 'job.title.prompt',
|
||||
defaultMessage: 'Next, search and select your current job title',
|
||||
description: 'Prompts the user to select their current job title or occupation.',
|
||||
},
|
||||
studentCheckboxPrompt: {
|
||||
id: 'student.checkbox.prompt',
|
||||
defaultMessage: 'I\'m a student',
|
||||
description: 'Label text for the corresponding checkbox',
|
||||
},
|
||||
currentlyLookingCheckboxPrompt: {
|
||||
id: 'currently.looking.checkbox.prompt',
|
||||
defaultMessage: 'I\'m currently looking for work',
|
||||
description: 'Label text for the corresponding checkbox',
|
||||
},
|
||||
careerInterestPrompt: {
|
||||
id: 'career.interest.prompt',
|
||||
defaultMessage: 'What careers are you interested in?',
|
||||
description: 'Prompts the user to select careers they are interested in pursuing.',
|
||||
},
|
||||
});
|
||||
|
||||
export default messages;
|
||||
@@ -0,0 +1,2 @@
|
||||
// eslint-disable-next-line import/prefer-default-export
|
||||
export { default as ViewResults } from './ViewResults';
|
||||
@@ -1,19 +1,96 @@
|
||||
import { IntlProvider } from '@edx/frontend-platform/i18n';
|
||||
import React from 'react';
|
||||
import { screen, render } from '@testing-library/react';
|
||||
import {
|
||||
screen, render, cleanup, fireEvent, act,
|
||||
} from '@testing-library/react';
|
||||
import { mergeConfig } from '@edx/frontend-platform';
|
||||
import { SkillsBuilder } from '..';
|
||||
import { SkillsBuilderModal } from '../skills-builder-modal';
|
||||
import { SkillsBuilderProvider, SkillsBuilderContext } from '../skills-builder-context';
|
||||
import { skillsInitialState } from '../data/reducer';
|
||||
|
||||
const SkillsBuilderWrapper = () => (
|
||||
jest.mock('react-instantsearch-hooks-web', () => ({
|
||||
// eslint-disable-next-line react/prop-types
|
||||
InstantSearch: ({ children }) => (<div>{children}</div>),
|
||||
useSearchBox: jest.fn(() => ({ refine: jest.fn() })),
|
||||
useHits: jest.fn(() => ({ hits: [{ name: 'Text File Engineer' }, { name: 'Screen Viewer' }] })),
|
||||
}));
|
||||
|
||||
const dispatchMock = jest.fn();
|
||||
|
||||
const contextValue = {
|
||||
state: {
|
||||
...skillsInitialState,
|
||||
},
|
||||
dispatch: dispatchMock,
|
||||
algolia: {
|
||||
// Without this, tests would fail to destructure `searchClient` in the <JobTitleSelect> component
|
||||
searchClient: {},
|
||||
},
|
||||
};
|
||||
|
||||
const SkillsBuilderWrapperWithContext = (value) => (
|
||||
<IntlProvider locale="en">
|
||||
<SkillsBuilder />
|
||||
<SkillsBuilderContext.Provider value={value}>
|
||||
<SkillsBuilderModal />
|
||||
</SkillsBuilderContext.Provider>
|
||||
</IntlProvider>
|
||||
);
|
||||
|
||||
describe('skills-builder', () => {
|
||||
it('should render a Skills Builder modal', () => {
|
||||
render(
|
||||
<SkillsBuilderWrapper />,
|
||||
);
|
||||
beforeAll(async () => {
|
||||
await mergeConfig({
|
||||
ALGOLIA_JOBS_INDEX_NAME: 'test-job-index-name',
|
||||
});
|
||||
});
|
||||
beforeEach(() => cleanup());
|
||||
|
||||
it('should render a Skills Builder modal with a prompt for the user', () => {
|
||||
act(() => {
|
||||
render(
|
||||
<IntlProvider locale="en">
|
||||
<SkillsBuilderProvider>
|
||||
<SkillsBuilder />
|
||||
</SkillsBuilderProvider>
|
||||
</IntlProvider>,
|
||||
);
|
||||
});
|
||||
expect(screen.getByText('Skills Builder')).toBeTruthy();
|
||||
expect(screen.getByText('First, tell us what you want to achieve')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should render the second prompt if a goal is selected', () => {
|
||||
render(
|
||||
SkillsBuilderWrapperWithContext(
|
||||
{
|
||||
...contextValue,
|
||||
state: {
|
||||
...contextValue.state,
|
||||
currentGoal: 'I want to start my career',
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(screen.getByText('Next, search and select your current job title')).toBeTruthy();
|
||||
|
||||
const checkbox = screen.getByRole('checkbox', { name: 'I\'m a student' });
|
||||
fireEvent.click(checkbox);
|
||||
expect(dispatchMock).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should render the third prompt if a goal is selected', () => {
|
||||
render(
|
||||
SkillsBuilderWrapperWithContext(
|
||||
{
|
||||
...contextValue,
|
||||
state: {
|
||||
...contextValue.state,
|
||||
currentGoal: 'I want to start my career',
|
||||
currentJobTitle: 'Goblin Guide',
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
expect(screen.getByText('What careers are you interested in?')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user