mirror of
https://github.com/ThisIsBenny/wishlist-app.git
synced 2025-06-07 05:57:41 +00:00
remove await functions on pages
Signed-off-by: Benny Samir Hierl <bennysamir@posteo.de>
This commit is contained in:
parent
ea2f6e7dc1
commit
17dce65127
9 changed files with 218 additions and 65 deletions
98
package-lock.json
generated
98
package-lock.json
generated
|
@ -8,6 +8,7 @@
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^3.8.1",
|
"@prisma/client": "^3.8.1",
|
||||||
|
"@vueuse/core": "^7.5.5",
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.25.0",
|
||||||
"fastify": "^3.27.0",
|
"fastify": "^3.27.0",
|
||||||
"fastify-compress": "^4.0.1",
|
"fastify-compress": "^4.0.1",
|
||||||
|
@ -895,6 +896,78 @@
|
||||||
"vue": "^3.0.1"
|
"vue": "^3.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@vueuse/core": {
|
||||||
|
"version": "7.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-7.5.5.tgz",
|
||||||
|
"integrity": "sha512-RBDqmIoGfak4h3xdXa/Av+ibkb8NY044wEy6+PG2FAWNaID8/FkqmSFjbxogrbmpSX1yZ1PBHrM8DUp/FrIpbg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@vueuse/shared": "7.5.5",
|
||||||
|
"vue-demi": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.1.0",
|
||||||
|
"vue": "^2.6.0 || ^3.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"vue": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vueuse/core/node_modules/@vueuse/shared": {
|
||||||
|
"version": "7.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-7.5.5.tgz",
|
||||||
|
"integrity": "sha512-mzzTsotHQRPnPAChy8iCv6ek/90CKYhAFyMRgNsMxpT0afZJkbMO/X0OaOu/1NuGbgb8UVjlsWKmCUgKTOF5hA==",
|
||||||
|
"dependencies": {
|
||||||
|
"vue-demi": "*"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.1.0",
|
||||||
|
"vue": "^2.6.0 || ^3.2.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
|
"vue": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@vueuse/core/node_modules/vue-demi": {
|
||||||
|
"version": "0.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.1.tgz",
|
||||||
|
"integrity": "sha512-QL3ny+wX8c6Xm1/EZylbgzdoDolye+VpCXRhI2hug9dJTP3OUJ3lmiKN3CsVV3mOJKwFi0nsstbgob0vG7aoIw==",
|
||||||
|
"hasInstallScript": true,
|
||||||
|
"bin": {
|
||||||
|
"vue-demi-fix": "bin/vue-demi-fix.js",
|
||||||
|
"vue-demi-switch": "bin/vue-demi-switch.js"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/antfu"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@vue/composition-api": "^1.0.0-rc.1",
|
||||||
|
"vue": "^3.0.0-0 || ^2.6.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"@vue/composition-api": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/abab": {
|
"node_modules/abab": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
||||||
|
@ -7585,6 +7658,31 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
|
"@vueuse/core": {
|
||||||
|
"version": "7.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vueuse/core/-/core-7.5.5.tgz",
|
||||||
|
"integrity": "sha512-RBDqmIoGfak4h3xdXa/Av+ibkb8NY044wEy6+PG2FAWNaID8/FkqmSFjbxogrbmpSX1yZ1PBHrM8DUp/FrIpbg==",
|
||||||
|
"requires": {
|
||||||
|
"@vueuse/shared": "7.5.5",
|
||||||
|
"vue-demi": "*"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@vueuse/shared": {
|
||||||
|
"version": "7.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-7.5.5.tgz",
|
||||||
|
"integrity": "sha512-mzzTsotHQRPnPAChy8iCv6ek/90CKYhAFyMRgNsMxpT0afZJkbMO/X0OaOu/1NuGbgb8UVjlsWKmCUgKTOF5hA==",
|
||||||
|
"requires": {
|
||||||
|
"vue-demi": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"vue-demi": {
|
||||||
|
"version": "0.12.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.12.1.tgz",
|
||||||
|
"integrity": "sha512-QL3ny+wX8c6Xm1/EZylbgzdoDolye+VpCXRhI2hug9dJTP3OUJ3lmiKN3CsVV3mOJKwFi0nsstbgob0vG7aoIw==",
|
||||||
|
"requires": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"abab": {
|
"abab": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@prisma/client": "^3.8.1",
|
"@prisma/client": "^3.8.1",
|
||||||
|
"@vueuse/core": "^7.5.5",
|
||||||
"axios": "^0.25.0",
|
"axios": "^0.25.0",
|
||||||
"fastify": "^3.27.0",
|
"fastify": "^3.27.0",
|
||||||
"fastify-compress": "^4.0.1",
|
"fastify-compress": "^4.0.1",
|
||||||
|
|
21
src/App.vue
21
src/App.vue
|
@ -1,27 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="app max-w-[900px] mx-auto p-10">
|
<div class="app max-w-[900px] mx-auto p-10">
|
||||||
<main>
|
<main>
|
||||||
<router-view v-slot="{ Component }">
|
<router-view />
|
||||||
<template v-if="Component">
|
|
||||||
<keep-alive>
|
|
||||||
<suspense>
|
|
||||||
<component :is="Component"></component>
|
|
||||||
<template #fallback>
|
|
||||||
<div
|
|
||||||
class="flex flex-row space-x-2 items-center content-center justify-center m-20"
|
|
||||||
>
|
|
||||||
<IconSpinner class="w-4 h-4" />
|
|
||||||
<span> Lade Daten... </span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</suspense>
|
|
||||||
</keep-alive>
|
|
||||||
</template>
|
|
||||||
</router-view>
|
|
||||||
</main>
|
</main>
|
||||||
<modal-overlay />
|
<modal-overlay />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
|
||||||
import IconSpinner from '@/components/icons/IconSpinner.vue'
|
|
||||||
</script>
|
|
||||||
|
|
8
src/components/icons/IconError.vue
Normal file
8
src/components/icons/IconError.vue
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
<template>
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M11,15H13V17H11V15M11,7H13V13H11V7M12,2C6.47,2 2,6.5 2,12A10,10 0 0,0 12,22A10,10 0 0,0 22,12A10,10 0 0,0 12,2M12,20A8,8 0 0,1 4,12A8,8 0 0,1 12,4A8,8 0 0,1 20,12A8,8 0 0,1 12,20Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</template>
|
5
src/components/icons/index.ts
Normal file
5
src/components/icons/index.ts
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
export { default as IconError } from './IconError.vue'
|
||||||
|
export { default as IconCart } from './IconCart.vue'
|
||||||
|
export { default as IconImagePlaceholder } from './IconImagePlaceholder.vue'
|
||||||
|
export { default as IconLink } from './IconLink.vue'
|
||||||
|
export { default as IconSpinner } from './IconSpinner.vue'
|
|
@ -1,21 +1,36 @@
|
||||||
import apiService from '@/services/apiService'
|
import apiService from '@/services/apiService'
|
||||||
import { Wishlist, WishlistItem } from '@/types'
|
import { Wishlist, WishlistItem } from '@/types'
|
||||||
import { reactive } from 'vue'
|
import { ref } from 'vue'
|
||||||
|
import { toReactive } from '@vueuse/core'
|
||||||
const apiClient = apiService.getClient()
|
const apiClient = apiService.getClient()
|
||||||
|
|
||||||
const getBySlugUrl = async (slugText: string): Promise<Wishlist> => {
|
const refState = ref<Wishlist | any>({})
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const hasError = ref(false)
|
||||||
|
|
||||||
|
const fetchBySlugUrl = async (slugText: string): Promise<void> => {
|
||||||
|
isLoading.value = true
|
||||||
|
try {
|
||||||
const { data } = await apiClient.get(`/wishlist/${slugText}`)
|
const { data } = await apiClient.get(`/wishlist/${slugText}`)
|
||||||
return data
|
refState.value = data
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error(error)
|
||||||
|
hasError.value = true
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateItem = async (item: WishlistItem): Promise<void> => {
|
const updateItem = async (item: WishlistItem): Promise<void> => {
|
||||||
await apiClient.put(`/wishlist/${item.wishlistId}/item/${item.id}`, item)
|
await apiClient.put(`/wishlist/${item.wishlistId}/item/${item.id}`, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useWishlistStore = async (slugText: string) => {
|
export const useWishlistStore = (slugText: string) => {
|
||||||
const list = reactive(await getBySlugUrl(slugText))
|
fetchBySlugUrl(slugText)
|
||||||
return reactive({
|
return {
|
||||||
list,
|
list: toReactive(refState),
|
||||||
|
isLoading,
|
||||||
|
hasError,
|
||||||
updateItem,
|
updateItem,
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,30 @@
|
||||||
import apiService from '@/services/apiService'
|
import apiService from '@/services/apiService'
|
||||||
import { Wishlist } from '@/types'
|
import { Wishlist } from '@/types'
|
||||||
import { reactive } from 'vue'
|
import { ref } from 'vue'
|
||||||
const apiClient = apiService.getClient()
|
const apiClient = apiService.getClient()
|
||||||
const prefix = '/wishlist'
|
const prefix = '/wishlist'
|
||||||
|
|
||||||
export const getAll = async (): Promise<Wishlist[]> => {
|
const refState = ref<Wishlist[]>([])
|
||||||
|
const isLoading = ref(false)
|
||||||
|
const hasError = ref(false)
|
||||||
|
|
||||||
|
export const loadAll = async (): Promise<void> => {
|
||||||
|
isLoading.value = true
|
||||||
|
try {
|
||||||
const { data } = await apiClient.get(prefix)
|
const { data } = await apiClient.get(prefix)
|
||||||
return data
|
refState.value = data
|
||||||
|
} catch (error: any) {
|
||||||
|
hasError.value = true
|
||||||
|
} finally {
|
||||||
|
isLoading.value = false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useWishlistsStore = async () => {
|
export const useWishlistsStore = () => {
|
||||||
const lists = reactive(await getAll())
|
loadAll()
|
||||||
return reactive({
|
return {
|
||||||
lists,
|
lists: refState,
|
||||||
})
|
hasError,
|
||||||
|
isLoading,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,16 @@
|
||||||
import { WishlistItem as WishlistItemType } from '@/types'
|
import { WishlistItem as WishlistItemType } from '@/types'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import Tile from '@/components/Tile.vue'
|
import Tile from '@/components/Tile.vue'
|
||||||
|
import { IconSpinner, IconError } from '@/components/icons'
|
||||||
import WishlistItem from '@/components/WishlistItem.vue'
|
import WishlistItem from '@/components/WishlistItem.vue'
|
||||||
import { useWishlistStore, useModal } from '@/composables'
|
import { useWishlistStore, useModal } from '@/composables'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
const modal = useModal()
|
const modal = useModal()
|
||||||
const wishlistStore = await useWishlistStore(route.params.slug as string)
|
const { list, isLoading, hasError, updateItem } = useWishlistStore(
|
||||||
const list = wishlistStore.list
|
route.params.slug as string
|
||||||
|
)
|
||||||
const notBoughtItems = computed(() => {
|
const notBoughtItems = computed(() => {
|
||||||
return list.items.filter((item: WishlistItemType) => item.bought === false)
|
return list.items.filter((item: WishlistItemType) => item.bought === false)
|
||||||
})
|
})
|
||||||
|
@ -21,12 +23,27 @@ const bought = async (item: WishlistItemType): Promise<void> => {
|
||||||
)
|
)
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
item.bought = true
|
item.bought = true
|
||||||
wishlistStore.updateItem(item)
|
updateItem(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div
|
||||||
|
v-if="isLoading"
|
||||||
|
class="flex flex-row space-x-2 items-center content-center justify-center m-20"
|
||||||
|
>
|
||||||
|
<IconSpinner class="w-4 h-4" />
|
||||||
|
<span> Lade Wunschliste... </span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="hasError"
|
||||||
|
class="flex flex-row space-x-2 items-center content-center justify-center m-20 text-red-500"
|
||||||
|
>
|
||||||
|
<IconError class="w-4 - h-4" />
|
||||||
|
<span> Es ist ein Fehler aufgetreten... </span>
|
||||||
|
</div>
|
||||||
|
<div v-else>
|
||||||
<div
|
<div
|
||||||
class="flex flex-col md:flex-row space-x-0 md:space-x-6 space-y-2 md:space-y-0 items-center"
|
class="flex flex-col md:flex-row space-x-0 md:space-x-6 space-y-2 md:space-y-0 items-center"
|
||||||
>
|
>
|
||||||
|
@ -52,4 +69,5 @@ const bought = async (item: WishlistItemType): Promise<void> => {
|
||||||
@bought="bought(item)"
|
@bought="bought(item)"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -1,13 +1,27 @@
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Tile from '@/components/Tile.vue'
|
import Tile from '@/components/Tile.vue'
|
||||||
|
import { IconSpinner, IconError } from '@/components/icons'
|
||||||
import { useWishlistsStore } from '@/composables'
|
import { useWishlistsStore } from '@/composables'
|
||||||
const wishlistStore = await useWishlistsStore()
|
const { lists, isLoading, hasError } = useWishlistsStore()
|
||||||
const lists = wishlistStore.lists
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h1 class="text-3xl text-center">Wunschlisten</h1>
|
<h1 class="text-3xl text-center">Wunschlisten</h1>
|
||||||
<div class="flex flex-row flex-wrap justify-around p-10">
|
<div
|
||||||
|
v-if="isLoading"
|
||||||
|
class="flex flex-row space-x-2 items-center content-center justify-center m-20"
|
||||||
|
>
|
||||||
|
<IconSpinner class="w-4 h-4" />
|
||||||
|
<span> Lade Wunschlisten... </span>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-else-if="hasError"
|
||||||
|
class="flex flex-row space-x-2 items-center content-center justify-center m-20 text-red-500"
|
||||||
|
>
|
||||||
|
<IconError class="w-4 - h-4" />
|
||||||
|
<span> Es ist ein Fehler aufgetreten... </span>
|
||||||
|
</div>
|
||||||
|
<div v-else class="flex flex-row flex-wrap justify-around p-10">
|
||||||
<router-link
|
<router-link
|
||||||
v-for="(item, index) in lists"
|
v-for="(item, index) in lists"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
|
Loading…
Add table
Reference in a new issue