integrated login page for vue app
This commit is contained in:
parent
751953ae70
commit
6eb42c4fce
|
|
@ -18,8 +18,11 @@
|
||||||
"@ionic/vue-router": "^8.0.0",
|
"@ionic/vue-router": "^8.0.0",
|
||||||
"axios": "^1.8.1",
|
"axios": "^1.8.1",
|
||||||
"ionicons": "^7.0.0",
|
"ionicons": "^7.0.0",
|
||||||
|
"vee-validate": "^4.15.0",
|
||||||
"vue": "^3.3.0",
|
"vue": "^3.3.0",
|
||||||
"vue-router": "^4.2.0"
|
"vue-router": "^4.2.0",
|
||||||
|
"vuex": "^4.1.0",
|
||||||
|
"yup": "^1.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@capacitor/cli": "6.1.2",
|
"@capacitor/cli": "6.1.2",
|
||||||
|
|
@ -3743,6 +3746,30 @@
|
||||||
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
|
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@vue/devtools-kit": {
|
||||||
|
"version": "7.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.7.2.tgz",
|
||||||
|
"integrity": "sha512-CY0I1JH3Z8PECbn6k3TqM1Bk9ASWxeMtTCvZr7vb+CHi+X/QwQm5F1/fPagraamKMAHVfuuCbdcnNg1A4CYVWQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/devtools-shared": "^7.7.2",
|
||||||
|
"birpc": "^0.2.19",
|
||||||
|
"hookable": "^5.5.3",
|
||||||
|
"mitt": "^3.0.1",
|
||||||
|
"perfect-debounce": "^1.0.0",
|
||||||
|
"speakingurl": "^14.0.1",
|
||||||
|
"superjson": "^2.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vue/devtools-shared": {
|
||||||
|
"version": "7.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.7.2.tgz",
|
||||||
|
"integrity": "sha512-uBFxnp8gwW2vD6FrJB8JZLUzVb6PNRG0B0jBnHsOH8uKyva2qINY8PTF5Te4QlTbMDqU5K6qtJDr6cNsKWhbOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"rfdc": "^1.4.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@vue/eslint-config-typescript": {
|
"node_modules/@vue/eslint-config-typescript": {
|
||||||
"version": "12.0.0",
|
"version": "12.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-12.0.0.tgz",
|
||||||
|
|
@ -4246,6 +4273,15 @@
|
||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/birpc": {
|
||||||
|
"version": "0.2.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.19.tgz",
|
||||||
|
"integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/blob-util": {
|
"node_modules/blob-util": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz",
|
||||||
|
|
@ -4727,6 +4763,21 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/copy-anything": {
|
||||||
|
"version": "3.0.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz",
|
||||||
|
"integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"is-what": "^4.1.8"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.13"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/mesqueeb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/core-js": {
|
"node_modules/core-js": {
|
||||||
"version": "3.39.0",
|
"version": "3.39.0",
|
||||||
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz",
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz",
|
||||||
|
|
@ -6233,6 +6284,12 @@
|
||||||
"he": "bin/he"
|
"he": "bin/he"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/hookable": {
|
||||||
|
"version": "5.5.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
|
||||||
|
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/html-encoding-sniffer": {
|
"node_modules/html-encoding-sniffer": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-3.0.0.tgz",
|
||||||
|
|
@ -6574,6 +6631,18 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-what": {
|
||||||
|
"version": "4.1.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
|
||||||
|
"integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.13"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/mesqueeb"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-wsl": {
|
"node_modules/is-wsl": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
|
||||||
|
|
@ -7225,6 +7294,12 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/mitt": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/mkdirp": {
|
"node_modules/mkdirp": {
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
|
||||||
|
|
@ -7647,6 +7722,12 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/perfect-debounce": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/performance-now": {
|
"node_modules/performance-now": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||||
|
|
@ -7837,6 +7918,12 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/property-expr": {
|
||||||
|
"version": "2.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
|
||||||
|
"integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/proto-list": {
|
"node_modules/proto-list": {
|
||||||
"version": "1.2.4",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
|
||||||
|
|
@ -8094,7 +8181,6 @@
|
||||||
"version": "1.4.1",
|
"version": "1.4.1",
|
||||||
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
|
||||||
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
|
"integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/rimraf": {
|
"node_modules/rimraf": {
|
||||||
|
|
@ -8433,6 +8519,15 @@
|
||||||
"source-map": "^0.6.0"
|
"source-map": "^0.6.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/speakingurl": {
|
||||||
|
"version": "14.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz",
|
||||||
|
"integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==",
|
||||||
|
"license": "BSD-3-Clause",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/split2": {
|
"node_modules/split2": {
|
||||||
"version": "4.2.0",
|
"version": "4.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
|
||||||
|
|
@ -8587,6 +8682,18 @@
|
||||||
"url": "https://github.com/sponsors/antfu"
|
"url": "https://github.com/sponsors/antfu"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/superjson": {
|
||||||
|
"version": "2.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.2.tgz",
|
||||||
|
"integrity": "sha512-5JRxVqC8I8NuOUjzBbvVJAKNM8qoVuH0O77h4WInc/qC2q5IreqKxYwgkga3PfA22OayK2ikceb/B26dztPl+Q==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"copy-anything": "^3.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/supports-color": {
|
"node_modules/supports-color": {
|
||||||
"version": "8.1.1",
|
"version": "8.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
|
||||||
|
|
@ -8725,6 +8832,12 @@
|
||||||
"readable-stream": "3"
|
"readable-stream": "3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tiny-case": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tiny-case/-/tiny-case-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-Eet/eeMhkO6TX8mnUteS9zgPbUMQa4I6Kkp5ORiBD5476/m+PIRiumP5tmh5ioJpH7k51Kehawy2UDfsnxxY8Q==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tinybench": {
|
"node_modules/tinybench": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz",
|
||||||
|
|
@ -8795,6 +8908,12 @@
|
||||||
"node": ">=8.0"
|
"node": ">=8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/toposort": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||||
|
"integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/tough-cookie": {
|
"node_modules/tough-cookie": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz",
|
||||||
|
|
@ -9067,6 +9186,40 @@
|
||||||
"uuid": "dist/bin/uuid"
|
"uuid": "dist/bin/uuid"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vee-validate": {
|
||||||
|
"version": "4.15.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.15.0.tgz",
|
||||||
|
"integrity": "sha512-PGJh1QCFwCBjbHu5aN6vB8macYVWrajbDvgo1Y/8fz9n/RVIkLmZCJDpUgu7+mUmCOPMxeyq7vXUOhbwAqdXcA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/devtools-api": "^7.5.2",
|
||||||
|
"type-fest": "^4.8.3"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.4.26"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vee-validate/node_modules/@vue/devtools-api": {
|
||||||
|
"version": "7.7.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-7.7.2.tgz",
|
||||||
|
"integrity": "sha512-1syn558KhyN+chO5SjlZIwJ8bV/bQ1nOVTG66t2RbG66ZGekyiYNmRO7X9BJCXQqPsFHlnksqvPhce2qpzxFnA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/devtools-kit": "^7.7.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/vee-validate/node_modules/type-fest": {
|
||||||
|
"version": "4.37.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.37.0.tgz",
|
||||||
|
"integrity": "sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==",
|
||||||
|
"license": "(MIT OR CC0-1.0)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/verror": {
|
"node_modules/verror": {
|
||||||
"version": "1.10.0",
|
"version": "1.10.0",
|
||||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||||
|
|
@ -9359,6 +9512,18 @@
|
||||||
"node": ">=10"
|
"node": ">=10"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/vuex": {
|
||||||
|
"version": "4.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/vuex/-/vuex-4.1.0.tgz",
|
||||||
|
"integrity": "sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@vue/devtools-api": "^6.0.0-beta.11"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"vue": "^3.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/w3c-xmlserializer": {
|
"node_modules/w3c-xmlserializer": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-4.0.0.tgz",
|
||||||
|
|
@ -9676,6 +9841,30 @@
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yup": {
|
||||||
|
"version": "1.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/yup/-/yup-1.6.1.tgz",
|
||||||
|
"integrity": "sha512-JED8pB50qbA4FOkDol0bYF/p60qSEDQqBD0/qeIrUCG1KbPBIQ776fCUNb9ldbPcSTxA69g/47XTo4TqWiuXOA==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"property-expr": "^2.0.5",
|
||||||
|
"tiny-case": "^1.0.3",
|
||||||
|
"toposort": "^2.0.2",
|
||||||
|
"type-fest": "^2.19.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/yup/node_modules/type-fest": {
|
||||||
|
"version": "2.19.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
|
||||||
|
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
|
||||||
|
"license": "(MIT OR CC0-1.0)",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,11 @@
|
||||||
"@ionic/vue-router": "^8.0.0",
|
"@ionic/vue-router": "^8.0.0",
|
||||||
"axios": "^1.8.1",
|
"axios": "^1.8.1",
|
||||||
"ionicons": "^7.0.0",
|
"ionicons": "^7.0.0",
|
||||||
|
"vee-validate": "^4.15.0",
|
||||||
"vue": "^3.3.0",
|
"vue": "^3.3.0",
|
||||||
"vue-router": "^4.2.0"
|
"vue-router": "^4.2.0",
|
||||||
|
"vuex": "^4.1.0",
|
||||||
|
"yup": "^1.6.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@capacitor/cli": "6.1.2",
|
"@capacitor/cli": "6.1.2",
|
||||||
|
|
@ -41,5 +44,5 @@
|
||||||
"vitest": "^0.34.6",
|
"vitest": "^0.34.6",
|
||||||
"vue-tsc": "^2.0.22"
|
"vue-tsc": "^2.0.22"
|
||||||
},
|
},
|
||||||
"description": "An Ionic project"
|
"description": "Bullpen session app"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { createApp } from 'vue'
|
import { createApp } from 'vue'
|
||||||
import App from './App.vue'
|
import App from './App.vue'
|
||||||
import router from './router';
|
import router from './router';
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
|
||||||
import { IonicVue } from '@ionic/vue';
|
import { IonicVue } from '@ionic/vue';
|
||||||
|
|
||||||
|
|
@ -34,7 +35,10 @@ import '@ionic/vue/css/palettes/dark.system.css';
|
||||||
/* Theme variables */
|
/* Theme variables */
|
||||||
import './theme/variables.css';
|
import './theme/variables.css';
|
||||||
|
|
||||||
|
import store from './store';
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
.use(store)
|
||||||
.use(IonicVue)
|
.use(IonicVue)
|
||||||
.use(router);
|
.use(router);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
export default class AuthHeader {
|
||||||
|
public header(): any {
|
||||||
|
const user = JSON.parse(localStorage.getItem('user') || '""');
|
||||||
|
|
||||||
|
if (user && user.accessToken) {
|
||||||
|
// return { Authorization: 'Bearer ' + user.accessToken }; // for Spring Boot back-end
|
||||||
|
return { 'x-access-token': user.accessToken }; // for Node.js Express back-end
|
||||||
|
} else {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
const API_URL = 'http://localhost:8080/api/auth/';
|
||||||
|
|
||||||
|
class AuthService {
|
||||||
|
public login(email: string, password: string) {
|
||||||
|
return axios
|
||||||
|
.post(API_URL + 'login', {
|
||||||
|
email,
|
||||||
|
password
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
if (response.data.accessToken) {
|
||||||
|
localStorage.setItem('user', JSON.stringify(response.data));
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public logout() {
|
||||||
|
localStorage.removeItem('user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public register(username: string, email: string, password: string) {
|
||||||
|
return axios.post(API_URL + 'register', {
|
||||||
|
username,
|
||||||
|
email,
|
||||||
|
password
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new AuthService();
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
import AuthService from '@/services/AuthService'
|
||||||
|
import Pitcher from "@/types/Pitcher";
|
||||||
|
|
||||||
|
import { Module, ActionContext } from 'vuex';
|
||||||
|
import { RootState } from './index';
|
||||||
|
|
||||||
|
export interface AuthState {
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
user: Pitcher | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const user = JSON.parse(localStorage.getItem('user') || '""');
|
||||||
|
|
||||||
|
const initialState = user
|
||||||
|
? { isAuthenticated: true, user }
|
||||||
|
: { isAuthenticated: false, user: null };
|
||||||
|
|
||||||
|
|
||||||
|
type AuthActionContext = ActionContext<AuthState, RootState>;
|
||||||
|
|
||||||
|
const auth: Module<AuthState, RootState> = {
|
||||||
|
namespaced: true,
|
||||||
|
state: initialState,
|
||||||
|
actions: {
|
||||||
|
login({ commit }: AuthActionContext, user) {
|
||||||
|
return AuthService.login(user.email, user.password).then(
|
||||||
|
user => {
|
||||||
|
commit('loginSuccess', user);
|
||||||
|
return Promise.resolve(user);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
commit('loginFailure');
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
},
|
||||||
|
logout({ commit }: AuthActionContext) {
|
||||||
|
AuthService.logout();
|
||||||
|
commit('logout');
|
||||||
|
},
|
||||||
|
register({ commit }: AuthActionContext, user) {
|
||||||
|
return AuthService.register(user.firstName, user.email, user.password).then(
|
||||||
|
response => {
|
||||||
|
commit('registerSuccess');
|
||||||
|
return Promise.resolve(response.data);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
commit('registerFailure');
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
loginSuccess(state, user) {
|
||||||
|
state.isAuthenticated = true;
|
||||||
|
state.user = user;
|
||||||
|
},
|
||||||
|
loginFailure(state) {
|
||||||
|
state.isAuthenticated = false;
|
||||||
|
state.user = null;
|
||||||
|
},
|
||||||
|
logout(state) {
|
||||||
|
state.isAuthenticated = false;
|
||||||
|
state.user = null;
|
||||||
|
},
|
||||||
|
registerSuccess(state) {
|
||||||
|
state.isAuthenticated = false;
|
||||||
|
},
|
||||||
|
registerFailure(state) {
|
||||||
|
state.isAuthenticated = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default auth;
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { createStore, Store } from 'vuex';
|
||||||
|
import auth, {AuthState} from './auth';
|
||||||
|
import pitchTypes, {PitchTypeState} from './pitchType';
|
||||||
|
|
||||||
|
// Root state type
|
||||||
|
export interface RootState {
|
||||||
|
auth: AuthState;
|
||||||
|
pitchTypes: PitchTypeState;
|
||||||
|
}
|
||||||
|
|
||||||
|
const store = createStore<RootState>({
|
||||||
|
modules: {
|
||||||
|
auth,
|
||||||
|
pitchTypes
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
export default store;
|
||||||
|
export type AppStore = Store<RootState>;
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
import {pitchTypeService} from '@/services/PitchTypeService'
|
||||||
|
import PitchType from "@/types/PitchType";
|
||||||
|
|
||||||
|
import { Module, ActionContext } from 'vuex';
|
||||||
|
import { RootState } from './index';
|
||||||
|
|
||||||
|
export interface PitchTypeState {
|
||||||
|
pitchTypes: PitchType[];
|
||||||
|
}
|
||||||
|
|
||||||
|
type PitchTypeActionContext = ActionContext<PitchTypeState, RootState>;
|
||||||
|
|
||||||
|
const pitchTypes: Module<PitchTypeState, RootState> = {
|
||||||
|
namespaced: true,
|
||||||
|
state: {pitchTypes: []},
|
||||||
|
actions: {
|
||||||
|
initialize({ commit }: PitchTypeActionContext) {
|
||||||
|
return pitchTypeService.getAllPitchTypes().then(
|
||||||
|
(pitchTypeList: PitchType[]) => {
|
||||||
|
commit('initializedPitchTypes', pitchTypeList);
|
||||||
|
return Promise.resolve(pitchTypeList);
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
return Promise.reject(error);
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mutations: {
|
||||||
|
initializedPitchTypes(state, pitchTypeList: PitchType[]) {
|
||||||
|
state.pitchTypes = pitchTypeList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default pitchTypes;
|
||||||
|
|
@ -10,59 +10,37 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
|
|
||||||
<ion-content class="ion-padding">
|
<ion-content class="ion-padding">
|
||||||
<div class="login-logo">
|
<form @submit="submit">
|
||||||
<img src="./../../public/favicon.png" alt="Ionic logo" />
|
<ion-row>
|
||||||
</div>
|
<ion-col>
|
||||||
|
|
||||||
<form novalidate @submit.prevent="onLogin">
|
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item>
|
|
||||||
<ion-input
|
|
||||||
label="Username"
|
|
||||||
labelPlacement="stacked"
|
|
||||||
v-model="username"
|
|
||||||
name="username"
|
|
||||||
type="text"
|
|
||||||
:spellcheck="false"
|
|
||||||
autocapitalize="off"
|
|
||||||
required
|
|
||||||
></ion-input>
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ion-item>
|
<ion-item>
|
||||||
<ion-input
|
<ion-icon name="person" class="icon-login"></ion-icon>
|
||||||
labelPlacement="stacked"
|
<ion-input name="user" v-model="email" v-bind="emailAttrs" type="text" required placeholder="Username"></ion-input>
|
||||||
label="Password"
|
|
||||||
v-model="password"
|
|
||||||
name="password"
|
|
||||||
type="password"
|
|
||||||
required
|
|
||||||
></ion-input>
|
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
<br />
|
||||||
|
<ion-item>
|
||||||
|
<ion-icon name="lock" class="icon-login"></ion-icon>
|
||||||
|
<ion-input name="password" v-model="password" v-bind="passwordAttrs" type="password" required placeholder="Password"></ion-input>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
<ion-row responsive-sm class="ion-padding">
|
|
||||||
<ion-col>
|
|
||||||
<ion-button :disabled="!canSubmit" type="submit" expand="block"
|
|
||||||
>Login</ion-button
|
|
||||||
>
|
|
||||||
</ion-col>
|
</ion-col>
|
||||||
|
</ion-row>
|
||||||
|
<ion-row>
|
||||||
<ion-col>
|
<ion-col>
|
||||||
<ion-button
|
<ion-button :disabled="!meta.valid" type="submit" fill="solid" expand="full">
|
||||||
:disabled="!canSubmit"
|
Login
|
||||||
@click="onSignup"
|
</ion-button>
|
||||||
color="light"
|
</ion-col>
|
||||||
expand="block"
|
</ion-row>
|
||||||
>Signup</ion-button
|
<ion-row>
|
||||||
>
|
<ion-col>
|
||||||
|
<pre>errors: {{ errors }}</pre>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
</ion-row>
|
</ion-row>
|
||||||
</form>
|
</form>
|
||||||
<ion-toast
|
|
||||||
:is-open="showToast"
|
|
||||||
:message="toastMessage"
|
|
||||||
:duration="2000"
|
|
||||||
></ion-toast>
|
|
||||||
</ion-content>
|
</ion-content>
|
||||||
</ion-page>
|
</ion-page>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -84,7 +62,7 @@
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ref } from "vue";
|
import { computed, ref, onMounted } from "vue";
|
||||||
import {
|
import {
|
||||||
IonPage,
|
IonPage,
|
||||||
IonHeader,
|
IonHeader,
|
||||||
|
|
@ -99,35 +77,55 @@ import {
|
||||||
IonRow,
|
IonRow,
|
||||||
IonCol,
|
IonCol,
|
||||||
IonInput,
|
IonInput,
|
||||||
IonToast,
|
IonIcon,
|
||||||
} from "@ionic/vue";
|
} from "@ionic/vue";
|
||||||
|
import { useForm } from 'vee-validate';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useStore } from 'vuex'
|
||||||
|
import { AppStore } from '@/store';
|
||||||
|
import * as yup from 'yup';
|
||||||
|
|
||||||
const username = ref("");
|
const loading = ref(false);
|
||||||
const password = ref("");
|
|
||||||
const submitted = ref(false);
|
|
||||||
|
|
||||||
const usernameValid = true;
|
const { meta, errors, handleSubmit, defineField } = useForm({
|
||||||
const passwordValid = true;
|
validationSchema: yup.object({
|
||||||
|
email: yup.string().email().required('No email provided.'),
|
||||||
|
password: yup.string().required('No password provided.').min(8)
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
const showToast = ref(false);
|
const [email, emailAttrs] = defineField('email');
|
||||||
const toastMessage = ref("");
|
const [password, passwordAttrs] = defineField('password');
|
||||||
|
|
||||||
const canSubmit = computed(
|
const router = useRouter();
|
||||||
() => username.value.trim() !== "" && password.value.trim() !== ""
|
const store = useStore<AppStore>();
|
||||||
);
|
|
||||||
|
|
||||||
const onLogin = () => {
|
const loggedIn = computed(() => store.state.auth.isAuthenticated);
|
||||||
submitted.value = true;
|
|
||||||
if (usernameValid && passwordValid) {
|
onMounted(() => {
|
||||||
|
if (loggedIn.value) {
|
||||||
|
router.push('/prepare');
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
|
|
||||||
const onSignup = () => {
|
const submit = handleSubmit(values => {
|
||||||
toastMessage.value = "Successfully logged in!";
|
store.dispatch('auth/login', {
|
||||||
|
email: values.email,
|
||||||
|
password: values.password,
|
||||||
|
}).then(
|
||||||
|
() => {
|
||||||
|
router.push('/prepare');
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
loading.value = false;
|
||||||
|
// message.value =
|
||||||
|
// (error.response && error.response.data && error.response.data.message) ||
|
||||||
|
// error.message ||
|
||||||
|
// error.toString();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}, ({errors}) => {
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
|
||||||
showToast.value = true;
|
|
||||||
|
|
||||||
username.value = "";
|
|
||||||
password.value = "";
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { Store } from 'vuex'
|
||||||
|
import Pitcher from 'types/Pitcher'
|
||||||
|
|
||||||
|
declare module 'vue' {
|
||||||
|
// declare your own auth states
|
||||||
|
interface State {
|
||||||
|
status: {
|
||||||
|
loggedIn: boolean
|
||||||
|
},
|
||||||
|
user: Pitcher | null
|
||||||
|
}
|
||||||
|
|
||||||
|
// provide typings for `this.$auth`
|
||||||
|
interface ComponentCustomProperties {
|
||||||
|
$store: Store<State>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -5,7 +5,7 @@ const bcrypt = require("bcryptjs");
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
const corsOptions = {
|
const corsOptions = {
|
||||||
origin: "http://localhost:8080"
|
origin: "http://localhost:5173"
|
||||||
};
|
};
|
||||||
|
|
||||||
app.use(cors(corsOptions));
|
app.use(cors(corsOptions));
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue