mirror of
https://github.com/ThisIsBenny/wishlist-app.git
synced 2025-06-07 05:57:41 +00:00
#3 Login page added to set api key
Signed-off-by: Benny Samir Hierl <bennysamir@posteo.de>
This commit is contained in:
parent
a362b67ec6
commit
c15b97d08a
12 changed files with 342 additions and 22 deletions
139
package-lock.json
generated
139
package-lock.json
generated
|
@ -17,9 +17,11 @@
|
|||
"fastify-helmet": "^7.0.1",
|
||||
"fastify-static": "^4.5.0",
|
||||
"open-graph-scraper": "^4.11.0",
|
||||
"vee-validate": "^4.5.8",
|
||||
"vue": "^3.2.27",
|
||||
"vue-i18n": "^9.2.0-beta.30",
|
||||
"vue-router": "^4.0.12"
|
||||
"vue-router": "^4.0.12",
|
||||
"yup": "^0.32.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.1.0",
|
||||
|
@ -158,6 +160,17 @@
|
|||
"node": ">=6.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/runtime": {
|
||||
"version": "7.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
|
||||
"integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
|
||||
"dependencies": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@babel/types": {
|
||||
"version": "7.16.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
|
||||
|
@ -534,6 +547,11 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/lodash": {
|
||||
"version": "4.14.178",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
|
||||
"integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw=="
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "16.11.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.21.tgz",
|
||||
|
@ -4473,8 +4491,12 @@
|
|||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"node_modules/lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||
},
|
||||
"node_modules/lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
|
@ -4640,6 +4662,11 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"node_modules/nanoclone": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
|
||||
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
|
||||
},
|
||||
"node_modules/nanoid": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
|
||||
|
@ -5459,6 +5486,11 @@
|
|||
"asap": "~2.0.3"
|
||||
}
|
||||
},
|
||||
"node_modules/property-expr": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
|
||||
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
|
@ -5743,6 +5775,11 @@
|
|||
"node": ">=8.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
},
|
||||
"node_modules/regexpp": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
|
||||
|
@ -6436,6 +6473,11 @@
|
|||
"integrity": "sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/toposort": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
|
||||
},
|
||||
"node_modules/touch": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
||||
|
@ -6754,6 +6796,17 @@
|
|||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/vee-validate": {
|
||||
"version": "4.5.8",
|
||||
"resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.5.8.tgz",
|
||||
"integrity": "sha512-XZx2J93rlET49CdIIoxG9R6wQNoT3RxUUw9ar3QbIhczpzbtlm4BQ+TpCA9DoYHKFlApcXnE28WU7m4quoPsCA==",
|
||||
"dependencies": {
|
||||
"@vue/devtools-api": "^6.0.0-beta.15"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vite": {
|
||||
"version": "2.7.13",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.7.13.tgz",
|
||||
|
@ -7374,6 +7427,23 @@
|
|||
"funding": {
|
||||
"url": "https://github.com/sponsors/sindresorhus"
|
||||
}
|
||||
},
|
||||
"node_modules/yup": {
|
||||
"version": "0.32.11",
|
||||
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
|
||||
"integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"@types/lodash": "^4.14.175",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"nanoclone": "^0.2.1",
|
||||
"property-expr": "^2.0.4",
|
||||
"toposort": "^2.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -7456,6 +7526,14 @@
|
|||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.16.10.tgz",
|
||||
"integrity": "sha512-Sm/S9Or6nN8uiFsQU1yodyDW3MWXQhFeqzMPM+t8MJjM+pLsnFVxFZzkpXKvUXh+Gz9cbMoYYs484+Jw/NTEFQ=="
|
||||
},
|
||||
"@babel/runtime": {
|
||||
"version": "7.17.2",
|
||||
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.2.tgz",
|
||||
"integrity": "sha512-hzeyJyMA1YGdJTuWU0e/j4wKXrU4OMFvY2MSlaI9B7VQb0r5cxTE3EAIS2Q7Tn2RIcDkRvTA/v2JsAEhxe99uw==",
|
||||
"requires": {
|
||||
"regenerator-runtime": "^0.13.4"
|
||||
}
|
||||
},
|
||||
"@babel/types": {
|
||||
"version": "7.16.8",
|
||||
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.16.8.tgz",
|
||||
|
@ -7765,6 +7843,11 @@
|
|||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"@types/lodash": {
|
||||
"version": "4.14.178",
|
||||
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
|
||||
"integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw=="
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "16.11.21",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.21.tgz",
|
||||
|
@ -10675,8 +10758,12 @@
|
|||
"lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
|
||||
},
|
||||
"lodash-es": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
|
||||
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
|
||||
},
|
||||
"lodash.merge": {
|
||||
"version": "4.6.2",
|
||||
|
@ -10799,6 +10886,11 @@
|
|||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
|
||||
},
|
||||
"nanoclone": {
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
|
||||
"integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
|
||||
},
|
||||
"nanoid": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.2.0.tgz",
|
||||
|
@ -11400,6 +11492,11 @@
|
|||
"asap": "~2.0.3"
|
||||
}
|
||||
},
|
||||
"property-expr": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.5.tgz",
|
||||
"integrity": "sha512-IJUkICM5dP5znhCckHSv30Q4b5/JA5enCtkRHYaOVOAocnH/1BQEYTC5NMfT3AVl/iXKdr3aqQbQn9DxyWknwA=="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
|
@ -11642,6 +11739,11 @@
|
|||
"picomatch": "^2.2.1"
|
||||
}
|
||||
},
|
||||
"regenerator-runtime": {
|
||||
"version": "0.13.9",
|
||||
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz",
|
||||
"integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA=="
|
||||
},
|
||||
"regexpp": {
|
||||
"version": "3.2.0",
|
||||
"resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
|
||||
|
@ -12160,6 +12262,11 @@
|
|||
"integrity": "sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ=",
|
||||
"dev": true
|
||||
},
|
||||
"toposort": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
|
||||
"integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA="
|
||||
},
|
||||
"touch": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
|
||||
|
@ -12390,6 +12497,14 @@
|
|||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
},
|
||||
"vee-validate": {
|
||||
"version": "4.5.8",
|
||||
"resolved": "https://registry.npmjs.org/vee-validate/-/vee-validate-4.5.8.tgz",
|
||||
"integrity": "sha512-XZx2J93rlET49CdIIoxG9R6wQNoT3RxUUw9ar3QbIhczpzbtlm4BQ+TpCA9DoYHKFlApcXnE28WU7m4quoPsCA==",
|
||||
"requires": {
|
||||
"@vue/devtools-api": "^6.0.0-beta.15"
|
||||
}
|
||||
},
|
||||
"vite": {
|
||||
"version": "2.7.13",
|
||||
"resolved": "https://registry.npmjs.org/vite/-/vite-2.7.13.tgz",
|
||||
|
@ -12844,6 +12959,20 @@
|
|||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
|
||||
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="
|
||||
},
|
||||
"yup": {
|
||||
"version": "0.32.11",
|
||||
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
|
||||
"integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
|
||||
"requires": {
|
||||
"@babel/runtime": "^7.15.4",
|
||||
"@types/lodash": "^4.14.175",
|
||||
"lodash": "^4.17.21",
|
||||
"lodash-es": "^4.17.21",
|
||||
"nanoclone": "^0.2.1",
|
||||
"property-expr": "^2.0.4",
|
||||
"toposort": "^2.0.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,11 @@
|
|||
"fastify-helmet": "^7.0.1",
|
||||
"fastify-static": "^4.5.0",
|
||||
"open-graph-scraper": "^4.11.0",
|
||||
"vee-validate": "^4.5.8",
|
||||
"vue": "^3.2.27",
|
||||
"vue-i18n": "^9.2.0-beta.30",
|
||||
"vue-router": "^4.0.12"
|
||||
"vue-router": "^4.0.12",
|
||||
"yup": "^0.32.11"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@rushstack/eslint-patch": "^1.1.0",
|
||||
|
|
|
@ -1,11 +1,24 @@
|
|||
<script lang="ts" setup>
|
||||
defineProps<{
|
||||
icon?: any
|
||||
}>()
|
||||
defineProps({
|
||||
icon: {
|
||||
type: Object,
|
||||
default: null,
|
||||
},
|
||||
mode: {
|
||||
type: String,
|
||||
default: 'secondary',
|
||||
},
|
||||
})
|
||||
</script>
|
||||
<template>
|
||||
<button
|
||||
class="inline-flex w-fit flex-row items-center justify-center rounded-md border-2 border-stone-200 py-1 px-2 text-stone-500 hover:bg-stone-100 dark:border-stone-700 dark:text-white/70 dark:hover:bg-stone-700"
|
||||
class="inline-flex w-fit flex-row items-center justify-center rounded-md border-2 py-1 px-2 disabled:cursor-not-allowed disabled:opacity-60"
|
||||
:class="{
|
||||
'border-0 bg-cyan-600 text-white disabled:bg-cyan-600 disabled:hover:bg-cyan-600 dark:bg-cyan-600 dark:hover:bg-cyan-600 dark:disabled:hover:bg-cyan-600':
|
||||
mode === 'primary',
|
||||
'border-stone-200 text-stone-500 hover:bg-stone-100 disabled:hover:bg-white dark:border-stone-700 dark:text-white/70 dark:hover:bg-stone-700 disabled:hover:dark:bg-stone-900':
|
||||
mode === 'secondary',
|
||||
}"
|
||||
>
|
||||
<component v-if="icon" :is="icon" class="mr-1 h-4 w-4" />
|
||||
<span>
|
||||
|
|
56
src/components/TextInput.vue
Normal file
56
src/components/TextInput.vue
Normal file
|
@ -0,0 +1,56 @@
|
|||
<template>
|
||||
<div class="relative mb-8">
|
||||
<label class="mb-1 block w-full" :for="name">{{ label }}</label>
|
||||
<input
|
||||
class="h-12 w-full rounded-md border-2 border-solid border-stone-300 bg-transparent px-2 outline-none dark:border-stone-700"
|
||||
:class="{ 'border-rose-500': !!errorMessage }"
|
||||
:name="name"
|
||||
:id="name"
|
||||
:type="type"
|
||||
:value="inputValue"
|
||||
:placeholder="placeholder"
|
||||
@input="handleChange"
|
||||
@blur="handleBlur"
|
||||
v-bind="$attrs"
|
||||
/>
|
||||
|
||||
<p class="absolute mt-2 text-sm text-rose-500" v-show="errorMessage">
|
||||
{{ errorMessage }}
|
||||
</p>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useField } from 'vee-validate'
|
||||
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text',
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
name: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
label: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
})
|
||||
const {
|
||||
value: inputValue,
|
||||
errorMessage,
|
||||
handleBlur,
|
||||
handleChange,
|
||||
} = useField(props.name, undefined, {
|
||||
initialValue: props.value,
|
||||
})
|
||||
</script>
|
15
src/composables/useAuth.ts
Normal file
15
src/composables/useAuth.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { readonly } from 'vue'
|
||||
import { useStorage } from '@vueuse/core'
|
||||
|
||||
const state = useStorage('auth-token', '')
|
||||
|
||||
const setToken = (token: string): void => {
|
||||
state.value = token
|
||||
}
|
||||
|
||||
export default () => {
|
||||
return {
|
||||
setToken,
|
||||
token: readonly(state),
|
||||
}
|
||||
}
|
|
@ -1,10 +1,17 @@
|
|||
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'
|
||||
import axios, {
|
||||
AxiosError,
|
||||
AxiosInstance,
|
||||
AxiosRequestConfig,
|
||||
AxiosResponse,
|
||||
} from 'axios'
|
||||
import { apiConfig } from '@/config'
|
||||
import { ref } from 'vue'
|
||||
import router from '../router'
|
||||
import useAuth from './useAuth'
|
||||
|
||||
const { token } = useAuth()
|
||||
const isLoading = ref(false)
|
||||
const error = ref(null)
|
||||
const error = ref<any | null>(null)
|
||||
|
||||
const config: AxiosRequestConfig = {
|
||||
baseURL: apiConfig.baseURL,
|
||||
|
@ -13,12 +20,20 @@ const config: AxiosRequestConfig = {
|
|||
const client: AxiosInstance = axios.create(config)
|
||||
|
||||
export const requestInterceptor = client.interceptors.request.use(
|
||||
function (config) {
|
||||
(config: AxiosRequestConfig): AxiosRequestConfig => {
|
||||
if (!config) {
|
||||
config = {}
|
||||
}
|
||||
if (!config.headers) {
|
||||
config.headers = {}
|
||||
}
|
||||
isLoading.value = true
|
||||
error.value = null
|
||||
config.headers.Authorization = token.value ? `Bearer ${token.value}` : ''
|
||||
|
||||
return config
|
||||
},
|
||||
function (err) {
|
||||
(err: AxiosError): Promise<AxiosError> => {
|
||||
isLoading.value = false
|
||||
error.value = err
|
||||
return Promise.reject(err)
|
||||
|
@ -26,11 +41,11 @@ export const requestInterceptor = client.interceptors.request.use(
|
|||
)
|
||||
|
||||
export const responseInterceptor = client.interceptors.response.use(
|
||||
function (response) {
|
||||
(response: AxiosResponse): AxiosResponse => {
|
||||
isLoading.value = false
|
||||
return response
|
||||
},
|
||||
function (err) {
|
||||
(err: AxiosError): Promise<AxiosError> => {
|
||||
isLoading.value = false
|
||||
if (err.response?.status === 404) {
|
||||
router.push({ name: 'notFound' })
|
||||
|
|
|
@ -16,6 +16,19 @@
|
|||
}
|
||||
},
|
||||
"pages": {
|
||||
"login-view": {
|
||||
"main": {
|
||||
"title": {
|
||||
"text": "Anmelden"
|
||||
},
|
||||
"form": {
|
||||
"api-key": {
|
||||
"placeholder": "API-Key",
|
||||
"error-requried": "API-Key wird benötigt"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"detail-view": {
|
||||
"main": {
|
||||
"empty-list": {
|
||||
|
|
|
@ -16,6 +16,19 @@
|
|||
}
|
||||
},
|
||||
"pages": {
|
||||
"login-view": {
|
||||
"main": {
|
||||
"title": {
|
||||
"text": "Login"
|
||||
},
|
||||
"form": {
|
||||
"api-key": {
|
||||
"placeholder": "API-Key",
|
||||
"error-requried": "API-Key is required"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"detail-view": {
|
||||
"main": {
|
||||
"empty-list": {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { createRouter, createWebHistory } from 'vue-router'
|
||||
import HomeView from '@/views/HomeView.vue'
|
||||
import LoginView from '@/views/LoginView.vue'
|
||||
import DetailView from '@/views/DetailView.vue'
|
||||
|
||||
const router = createRouter({
|
||||
|
@ -10,6 +11,11 @@ const router = createRouter({
|
|||
name: 'home',
|
||||
component: HomeView,
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: LoginView,
|
||||
},
|
||||
{
|
||||
path: '/:slug',
|
||||
name: 'detail',
|
||||
|
@ -18,7 +24,7 @@ const router = createRouter({
|
|||
{
|
||||
name: 'notFound',
|
||||
path: '/:pathMatch(.*)*',
|
||||
component: () => import('@/views/NotFound.vue'),
|
||||
component: () => import('@/views/NotFoundView.vue'),
|
||||
},
|
||||
],
|
||||
})
|
||||
|
|
|
@ -69,6 +69,7 @@ const bought = async (item: WishlistItemType): Promise<void> => {
|
|||
class="flex flex-col flex-wrap items-center justify-center text-center text-xl text-gray-600/75 dark:text-white/70 sm:flex-row sm:space-x-2 sm:text-left"
|
||||
>
|
||||
<IconNoGift class="h-10 w-10" />
|
||||
|
||||
<span>{{ t('pages.detail-view.main.empty-list.text') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
56
src/views/LoginView.vue
Normal file
56
src/views/LoginView.vue
Normal file
|
@ -0,0 +1,56 @@
|
|||
<script setup lang="ts">
|
||||
import { useRouter } from 'vue-router'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { Form } from 'vee-validate'
|
||||
import { object, string } from 'yup'
|
||||
import useAuth from '@/composables/useAuth'
|
||||
import BaseButton from '@/components/BaseButton.vue'
|
||||
import TextInput from '@/components/TextInput.vue'
|
||||
|
||||
const router = useRouter()
|
||||
const { setToken } = useAuth()
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
const schema = object({
|
||||
'api-key': string().required(
|
||||
t('pages.login-view.main.form.api-key.error-requried')
|
||||
),
|
||||
})
|
||||
|
||||
const onSubmit = (values: any): void => {
|
||||
setToken(values['api-key'])
|
||||
router.push('/')
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex h-full">
|
||||
<div
|
||||
class="m-auto w-1/2 rounded-md border-2 border-stone-200 px-6 py-10 dark:border-stone-700"
|
||||
>
|
||||
<h1 class="text-semibold mb-8 text-center text-3xl">
|
||||
{{ t('pages.login-view.main.title.text') }}
|
||||
</h1>
|
||||
<Form
|
||||
@submit="onSubmit"
|
||||
:validation-schema="schema"
|
||||
v-slot="{ meta }"
|
||||
class="w-full flex-col space-y-3"
|
||||
>
|
||||
<TextInput
|
||||
name="api-key"
|
||||
type="text"
|
||||
:label="t('pages.login-view.main.form.api-key.placeholder')"
|
||||
autocomplete="off"
|
||||
/>
|
||||
<BaseButton
|
||||
class="h-12 w-full"
|
||||
mode="primary"
|
||||
:disabled="!meta.dirty || !meta.valid"
|
||||
>Submit</BaseButton
|
||||
>
|
||||
</Form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
|
@ -1,3 +1,9 @@
|
|||
<script setup lang="ts">
|
||||
import { IconCloudQuestion } from '@/components/icons'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="mt-20 flex flex-col flex-wrap items-center justify-center text-center text-xl sm:flex-row sm:space-x-2 sm:text-left"
|
||||
|
@ -6,8 +12,3 @@
|
|||
<h1>{{ t('errors.not-found.text') }}</h1>
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { IconCloudQuestion } from '@/components/icons'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
const { t } = useI18n()
|
||||
</script>
|
Loading…
Add table
Reference in a new issue