some improvments

Signed-off-by: Benny Samir Hierl <bennysamir@posteo.de>
This commit is contained in:
Benny Samir Hierl 2022-02-19 01:27:25 +01:00
parent 6158b7a395
commit 31bee89c1d
6 changed files with 93 additions and 62 deletions

2
components.d.ts vendored
View file

@ -35,4 +35,4 @@ declare module 'vue' {
} }
} }
export { } export {}

View file

@ -11,19 +11,7 @@
<IconError class="h-4 w-4 fill-red-500" /> <IconError class="h-4 w-4 fill-red-500" />
<span>{{ t('errors.generic.text') }}</span> <span>{{ t('errors.generic.text') }}</span>
</div> </div>
<suspense v-else> <component v-else :is="Component"></component>
<template #default>
<component :is="Component"></component>
</template>
<template #fallback>
<div
class="m-20 flex flex-row content-center items-center justify-center space-x-2"
>
<IconSpinner class="h-4 w-4" />
<span> {{ t('common.loading.text') }} </span>
</div>
</template>
</suspense>
</template> </template>
</router-view> </router-view>
</main> </main>
@ -31,6 +19,7 @@
</div> </div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { useTitle } from '@vueuse/core'
import { onErrorCaptured, ref } from 'vue' import { onErrorCaptured, ref } from 'vue'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
const { t } = useI18n() const { t } = useI18n()
@ -40,6 +29,8 @@ const error = ref()
onErrorCaptured((e: unknown) => { onErrorCaptured((e: unknown) => {
console.error(e) console.error(e)
error.value = e error.value = e
useTitle(t('errors.generic.text'))
return false return false
}) })
</script> </script>

View file

@ -1,13 +1,14 @@
import { apiConfig } from '@/config' import { apiConfig } from '@/config'
import { useAuth } from './useAuth' import { useAuth } from './useAuth'
import { createFetch } from '@vueuse/core' import { createFetch } from '@vueuse/core'
import router from '../router'
const { token } = useAuth() const { token } = useAuth()
export const useFetch = createFetch({ export const useFetch = createFetch({
baseUrl: apiConfig.baseURL, baseUrl: apiConfig.baseURL,
options: { options: {
async beforeFetch({ options }) { beforeFetch({ options }) {
if (token.value) { if (token.value) {
options.headers = { options.headers = {
...options.headers, ...options.headers,
@ -17,5 +18,12 @@ export const useFetch = createFetch({
return { options } return { options }
}, },
onFetchError(ctx) {
if (ctx.data && ctx.data.statusCode === 404) {
router.push({ name: 'notFound' })
}
return ctx
},
}, },
}) })

View file

@ -13,7 +13,10 @@ const update = async (updatedData: Wishlist): Promise<void> => {
...state.value, ...state.value,
...updatedData, ...updatedData,
} }
const { data } = await useFetch(`/wishlist/${id}`).put(payload).json() const { data, error } = await useFetch(`/wishlist/${id}`).put(payload).json()
if (error.value) {
throw error.value
}
state.value = { state.value = {
...state.value, ...state.value,
...(<Wishlist>data.value), ...(<Wishlist>data.value),
@ -25,7 +28,12 @@ const createItem = async (values: WishlistItem): Promise<void> => {
const payload = { const payload = {
...values, ...values,
} }
const { data } = await useFetch(`/wishlist/${id}/item`).post(payload).json() const { data, error } = await useFetch(`/wishlist/${id}/item`)
.post(payload)
.json()
if (error.value) {
throw error.value
}
state.value?.items?.push(unref(data)) state.value?.items?.push(unref(data))
} }
@ -39,9 +47,14 @@ const updateItem = async (
...newValues, ...newValues,
} }
const { data } = await useFetch(`/wishlist/${id}/item/${currentValues.id}`) const { data, error } = await useFetch(
`/wishlist/${id}/item/${currentValues.id}`
)
.put(payload) .put(payload)
.json() .json()
if (error.value) {
throw error.value
}
state.value?.items?.splice( state.value?.items?.splice(
state.value.items.indexOf(currentValues), state.value.items.indexOf(currentValues),
1, 1,
@ -50,12 +63,22 @@ const updateItem = async (
} }
const itemBought = async (item: WishlistItem): Promise<void> => { const itemBought = async (item: WishlistItem): Promise<void> => {
await useFetch(`/wishlist/${item.wishlistId}/item/${item.id}/bought`).post() const { error } = await useFetch(
`/wishlist/${item.wishlistId}/item/${item.id}/bought`
).post()
if (error.value) {
throw error.value
}
item.bought = true item.bought = true
} }
const itemDelete = async (item: WishlistItem): Promise<void> => { const itemDelete = async (item: WishlistItem): Promise<void> => {
await useFetch(`/wishlist/${item.wishlistId}/item/${item.id}`).delete() const { error } = await useFetch(
`/wishlist/${item.wishlistId}/item/${item.id}`
).delete()
if (error.value) {
throw error.value
}
state.value?.items?.splice(state.value.items.indexOf(item), 1) state.value?.items?.splice(state.value.items.indexOf(item), 1)
} }

View file

@ -87,53 +87,60 @@ const handleDeleteItem = async (item: WishlistItemType): Promise<void> => {
</script> </script>
<template> <template>
<div v-if="isFinished" class="h-full"> <div class="h-full">
<div <div
class="flex flex-col items-center space-x-0 space-y-2 md:flex-row md:space-x-6 md:space-y-0" v-if="!isFinished"
v-if="state !== undefined" class="m-20 flex flex-row content-center items-center justify-center space-x-2"
> >
<ImageTile :image-src="state.imageSrc" class="shrink-0"></ImageTile> <IconSpinner class="h-4 w-4" />
<div v-if="!editModeIsActive"> <span> {{ t('common.loading.text') }} </span>
<h1 class="mb-2 text-center text-2xl font-bold md:text-left">
{{ state.title }}
</h1>
<p class="text-lg">
{{ state.description }}
</p>
</div>
<FormWishlist v-else :wishlist="state" @update="handleUpdateWishlist" />
</div> </div>
<div <div v-else-if="state !== undefined">
v-if="filteredItems.length > 0"
class="flex flex-col space-y-14 py-10 md:space-y-8"
>
<FormWishlistItem
v-if="editModeIsActive"
mode="create"
@create="handleCreateItem"
/>
<div v-for="item in filteredItems" :key="item.id">
<WishlistItem
v-if="!editModeIsActive"
:item="item"
@bought="handleBought(item)"
/>
<FormWishlistItem
v-else
:item="item"
mode="update"
@update="(updateValues) => handleUpdateItem(item, updateValues)"
@delete="handleDeleteItem(item)"
/>
</div>
</div>
<div v-else class="flex h-1/2 w-full justify-center">
<div <div
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" class="flex flex-col items-center space-x-0 space-y-2 md:flex-row md:space-x-6 md:space-y-0"
> >
<IconNoGift class="h-10 w-10 fill-gray-600/75 dark:fill-white/70" /> <ImageTile :image-src="state.imageSrc" class="shrink-0"></ImageTile>
<div v-if="!editModeIsActive">
<span>{{ t('pages.detail-view.main.empty-list.text') }}</span> <h1 class="mb-2 text-center text-2xl font-bold md:text-left">
{{ state.title }}
</h1>
<p class="text-lg">
{{ state.description }}
</p>
</div>
<FormWishlist v-else :wishlist="state" @update="handleUpdateWishlist" />
</div>
<div
v-if="filteredItems.length > 0"
class="flex flex-col space-y-14 py-10 md:space-y-8"
>
<FormWishlistItem
v-if="editModeIsActive"
mode="create"
@create="handleCreateItem"
/>
<div v-for="item in filteredItems" :key="item.id">
<WishlistItem
v-if="!editModeIsActive"
:item="item"
@bought="handleBought(item)"
/>
<FormWishlistItem
v-else
:item="item"
mode="update"
@update="(updateValues) => handleUpdateItem(item, updateValues)"
@delete="handleDeleteItem(item)"
/>
</div>
</div>
<div v-else class="flex h-1/2 w-full justify-center">
<div
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 fill-gray-600/75 dark:fill-white/70" />
<span>{{ t('pages.detail-view.main.empty-list.text') }}</span>
</div>
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,6 +1,8 @@
<script setup lang="ts"> <script setup lang="ts">
import { useTitle } from '@vueuse/core'
import { useI18n } from 'vue-i18n' import { useI18n } from 'vue-i18n'
const { t } = useI18n() const { t } = useI18n()
useTitle(t('errors.not-found.text'))
</script> </script>
<template> <template>