mirror of
https://github.com/ThisIsBenny/wishlist-app.git
synced 2025-04-19 15:27:41 +00:00
add wishlist item page added for bookmark adding
Signed-off-by: Benny Samir Hierl <bennysamir@posteo.de>
This commit is contained in:
parent
f9147e9751
commit
2ee5c03935
8 changed files with 155 additions and 9 deletions
4
components.d.ts
vendored
4
components.d.ts
vendored
|
@ -28,8 +28,6 @@ declare module 'vue' {
|
|||
IconToggleOn: typeof import('./src/components/icons/IconToggleOn.vue')['default']
|
||||
ImagePreview: typeof import('./src/components/ImagePreview.vue')['default']
|
||||
ImageTile: typeof import('./src/components/ImageTile.vue')['default']
|
||||
'ImageTile copy': typeof import('./src/components/ImageTile copy.vue')['default']
|
||||
ImageTilePlaceholder: typeof import('./src/components/ImageTilePlaceholder.vue')['default']
|
||||
InputFile: typeof import('./src/components/InputFile.vue')['default']
|
||||
InputText: typeof import('./src/components/InputText.vue')['default']
|
||||
InputTextArea: typeof import('./src/components/InputTextArea.vue')['default']
|
||||
|
@ -39,4 +37,4 @@ declare module 'vue' {
|
|||
}
|
||||
}
|
||||
|
||||
export {}
|
||||
export { }
|
||||
|
|
|
@ -24,7 +24,7 @@ export const fetchOpenGraph = <RouteOptions>{
|
|||
properties: {
|
||||
title: { type: 'string' },
|
||||
description: { type: 'string' },
|
||||
image: { type: 'string' },
|
||||
imageSrc: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -42,7 +42,7 @@ export const fetchOpenGraph = <RouteOptions>{
|
|||
reply.send({
|
||||
title: result.ogTitle || '',
|
||||
description: result.ogDescription || '',
|
||||
image,
|
||||
imageSrc: image,
|
||||
})
|
||||
}
|
||||
},
|
||||
|
|
|
@ -47,8 +47,11 @@ const deleteWishlist = async (): Promise<void> => {
|
|||
}
|
||||
}
|
||||
|
||||
const createItem = async (values: WishlistItem): Promise<void> => {
|
||||
const id = state.value?.id
|
||||
const createItem = async (
|
||||
values: WishlistItem,
|
||||
wishlistId?: string
|
||||
): Promise<void> => {
|
||||
const id = wishlistId || state.value?.id
|
||||
const payload = {
|
||||
...values,
|
||||
}
|
||||
|
|
|
@ -62,6 +62,17 @@
|
|||
"text": "Erstelle eine Wunschliste"
|
||||
}
|
||||
},
|
||||
"create-wishlist-item-view": {
|
||||
"title": {
|
||||
"text": "Eintrag hinzufügen"
|
||||
},
|
||||
"loading": {
|
||||
"text": "Lade Daten der übermittelten URL"
|
||||
},
|
||||
"headline-wishlist-selection": {
|
||||
"text": "Zu welcher Wunschliste möchten Sie etwas hinzufügen?"
|
||||
}
|
||||
},
|
||||
"detail-view": {
|
||||
"main": {
|
||||
"empty-list": {
|
||||
|
|
|
@ -54,6 +54,17 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"create-wishlist-item-view": {
|
||||
"title": {
|
||||
"text": "Add item"
|
||||
},
|
||||
"loading": {
|
||||
"text": "Loading data from provided URL"
|
||||
},
|
||||
"headline-wishlist-selection": {
|
||||
"text": "To which wish list would you like to add the new item?"
|
||||
}
|
||||
},
|
||||
"create-wishlist-view": {
|
||||
"title": {
|
||||
"text": "Create a wishlist"
|
||||
|
|
|
@ -2,7 +2,10 @@ import { createRouter, createWebHistory } from 'vue-router'
|
|||
import HomeView from '@/views/HomeView.vue'
|
||||
import LoginView from '@/views/LoginView.vue'
|
||||
import CreateWishlistView from '@/views/CreateWishlistView.vue'
|
||||
import AddWishlistItemView from '@/views/AddWishlistItemView.vue'
|
||||
import DetailView from '@/views/DetailView.vue'
|
||||
import { useAuth } from '@/composables'
|
||||
const { isAuthenticated } = useAuth()
|
||||
|
||||
const router = createRouter({
|
||||
history: createWebHistory(import.meta.env.BASE_URL),
|
||||
|
@ -11,28 +14,45 @@ const router = createRouter({
|
|||
path: '/',
|
||||
name: 'home',
|
||||
component: HomeView,
|
||||
meta: { requiresAuth: false },
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
name: 'login',
|
||||
component: LoginView,
|
||||
meta: { requiresAuth: false },
|
||||
},
|
||||
{
|
||||
path: '/create-wishlist',
|
||||
name: 'create-wishlist',
|
||||
component: CreateWishlistView,
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: '/add-wishlist-item',
|
||||
name: 'add-wishlist--item',
|
||||
component: AddWishlistItemView,
|
||||
meta: { requiresAuth: true },
|
||||
},
|
||||
{
|
||||
path: '/:slug',
|
||||
name: 'detail',
|
||||
component: DetailView,
|
||||
meta: { requiresAuth: false },
|
||||
},
|
||||
{
|
||||
name: 'notFound',
|
||||
path: '/:pathMatch(.*)*',
|
||||
component: () => import('@/views/NotFoundView.vue'),
|
||||
meta: { requiresAuth: false },
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
router.beforeEach((to, from) => {
|
||||
if (!isAuthenticated.value && to.meta.requiresAuth === true) {
|
||||
return { name: 'login' }
|
||||
}
|
||||
})
|
||||
|
||||
export default router
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
export interface WishlistItem {
|
||||
id: number
|
||||
id?: number
|
||||
title: string
|
||||
url: string
|
||||
imageSrc: string
|
||||
description: string
|
||||
bought: boolean
|
||||
wishlistId: boolean
|
||||
wishlistId?: boolean
|
||||
}
|
||||
export interface Wishlist {
|
||||
id?: string
|
||||
|
|
103
src/views/AddWishlistItemView.vue
Normal file
103
src/views/AddWishlistItemView.vue
Normal file
|
@ -0,0 +1,103 @@
|
|||
<script setup lang="ts">
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { Wishlist, WishlistItem } from '@/types'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useWishlistsStore, useWishlistStore } from '@/composables'
|
||||
import { useToast } from 'vue-toastification'
|
||||
import { useFetch } from '@/composables/useFetch'
|
||||
import { syncRef, useTitle, watchOnce } from '@vueuse/core'
|
||||
import { Ref, ref } from 'vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const { t } = useI18n()
|
||||
const toast = useToast()
|
||||
|
||||
const isFinished = ref(true)
|
||||
const selectedWishlist: Ref<Wishlist | undefined> = ref()
|
||||
const prefillData = ref({
|
||||
title: '',
|
||||
description: '',
|
||||
imageSrc: '',
|
||||
url: '',
|
||||
bought: false,
|
||||
})
|
||||
|
||||
const { createItem } = useWishlistStore()
|
||||
|
||||
const {
|
||||
state: wishlists,
|
||||
isFinished: loadWishlistsFinished,
|
||||
fetch,
|
||||
} = useWishlistsStore()
|
||||
|
||||
fetch()
|
||||
|
||||
if (route.query.url) {
|
||||
prefillData.value.url = route.query.url as string
|
||||
const { data: opData, isFinished: opDataLoaded } = useFetch(
|
||||
`/utils/fetch-open-graph?url=${route.query.url}`
|
||||
).json()
|
||||
syncRef(opDataLoaded, isFinished)
|
||||
|
||||
watchOnce(opData, () => {
|
||||
prefillData.value = {
|
||||
...prefillData.value,
|
||||
...opData.value,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
useTitle(t('pages.create-wishlist-item-view.title.text'))
|
||||
|
||||
const handleCreateItem = async (values: WishlistItem): Promise<void> => {
|
||||
try {
|
||||
await createItem(values, selectedWishlist?.value?.id)
|
||||
toast.success(t('common.saved.text'))
|
||||
router.push(`/${selectedWishlist?.value?.slugUrlText}`)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
toast.error(t('common.saving-failed.text'))
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="h-full">
|
||||
<div
|
||||
v-if="!isFinished || !loadWishlistsFinished"
|
||||
class="flex h-1/2 w-full flex-col justify-center"
|
||||
>
|
||||
<div
|
||||
class="m-20 flex flex-row content-center items-center justify-center space-x-2"
|
||||
>
|
||||
<IconSpinner class="h-4 w-4" />
|
||||
<span> {{ t('pages.create-wishlist-item-view.loading.text') }} </span>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else-if="loadWishlistsFinished && selectedWishlist === undefined">
|
||||
<h1 class="text-center text-xl font-bold">
|
||||
{{
|
||||
t('pages.create-wishlist-item-view.headline-wishlist-selection.text')
|
||||
}}
|
||||
</h1>
|
||||
<div
|
||||
class="m-8 flex flex-row flex-wrap content-center items-center justify-center sm:space-x-2"
|
||||
>
|
||||
<div
|
||||
v-for="item in wishlists"
|
||||
:key="item.id"
|
||||
@click="() => (selectedWishlist = item)"
|
||||
class="cursor-pointer"
|
||||
>
|
||||
<ImageTile
|
||||
:title="item.title"
|
||||
:image-src="item.imageSrc"
|
||||
class="m-4"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<FormWishlistItem :item="prefillData" v-else @create="handleCreateItem" />
|
||||
</div>
|
||||
</template>
|
Loading…
Add table
Reference in a new issue