mirror of
https://github.com/ThisIsBenny/wishlist-app.git
synced 2025-04-19 23:37:41 +00:00
delete item option added
Signed-off-by: Benny Samir Hierl <bennysamir@posteo.de>
This commit is contained in:
parent
adf6014959
commit
ff35bb3144
9 changed files with 108 additions and 14 deletions
|
@ -16,6 +16,8 @@ defineProps({
|
||||||
:class="{
|
: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':
|
'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',
|
mode === 'primary',
|
||||||
|
'border-0 bg-rose-500 text-white disabled:bg-rose-500 disabled:hover:bg-rose-500 dark:bg-rose-500 dark:hover:bg-rose-500 dark:disabled:hover:bg-rose-500':
|
||||||
|
mode === 'danger',
|
||||||
'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':
|
'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',
|
mode === 'secondary',
|
||||||
}"
|
}"
|
||||||
|
@ -23,9 +25,8 @@ defineProps({
|
||||||
<component
|
<component
|
||||||
v-if="icon"
|
v-if="icon"
|
||||||
:is="icon"
|
:is="icon"
|
||||||
class="mr-1 h-4 w-4"
|
class="mr-1 h-4 w-4 fill-white"
|
||||||
:class="{
|
:class="{
|
||||||
'fill-white': mode === 'primary',
|
|
||||||
'fill-stone-500 dark:fill-white/70 ': mode === 'secondary',
|
'fill-stone-500 dark:fill-white/70 ': mode === 'secondary',
|
||||||
}"
|
}"
|
||||||
/>
|
/>
|
||||||
|
|
36
src/components/FormWishlistItem.vue
Normal file
36
src/components/FormWishlistItem.vue
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useI18n } from 'vue-i18n'
|
||||||
|
import ImagePreview from './ImagePreview.vue'
|
||||||
|
import { ButtonBase } from './'
|
||||||
|
import IconDelete from './icons/IconDelete.vue'
|
||||||
|
import { WishlistItem } from '@/types'
|
||||||
|
defineProps<{
|
||||||
|
item: WishlistItem
|
||||||
|
}>()
|
||||||
|
const { t } = useI18n()
|
||||||
|
|
||||||
|
const emits = defineEmits(['delete'])
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div
|
||||||
|
class="flex h-fit flex-col space-x-0 overflow-hidden rounded-md border-2 border-stone-200 dark:border-stone-700 sm:h-40 sm:flex-row sm:space-x-2"
|
||||||
|
>
|
||||||
|
<ImagePreview
|
||||||
|
class="max-h-44 flex-shrink-0 flex-grow-0 object-cover sm:aspect-[3/2]"
|
||||||
|
:src="item.imageSrc"
|
||||||
|
:alt="item.title"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div class="flex w-full flex-col justify-between p-2">
|
||||||
|
<span></span>
|
||||||
|
<ButtonBase
|
||||||
|
class="h-12 w-full"
|
||||||
|
mode="danger"
|
||||||
|
@click.prevent="() => emits('delete')"
|
||||||
|
:icon="IconDelete"
|
||||||
|
>{{ t('components.wishlist-item.delete-button.text') }}</ButtonBase
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
7
src/components/icons/IconDelete.vue
Normal file
7
src/components/icons/IconDelete.vue
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<template>
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M19 4h-3.5l-1-1h-5l-1 1H5v2h14M6 19a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7H6v12Z"
|
||||||
|
></path>
|
||||||
|
</svg>
|
||||||
|
</template>
|
|
@ -11,3 +11,4 @@ export { default as IconCloudQuestion } from './IconCloudQuestion.vue'
|
||||||
export { default as IconToggleOn } from './IconToggleOn.vue'
|
export { default as IconToggleOn } from './IconToggleOn.vue'
|
||||||
export { default as IconToggleOff } from './IconToggleOff.vue'
|
export { default as IconToggleOff } from './IconToggleOff.vue'
|
||||||
export { default as IconSave } from './IconSave.vue'
|
export { default as IconSave } from './IconSave.vue'
|
||||||
|
export { default as IconDelete } from './IconDelete.vue'
|
||||||
|
|
|
@ -8,4 +8,5 @@ export { default as InputFile } from './InputFile.vue'
|
||||||
export { default as InputTextArea } from './InputTextArea.vue'
|
export { default as InputTextArea } from './InputTextArea.vue'
|
||||||
export { default as Modal } from './Modal.vue'
|
export { default as Modal } from './Modal.vue'
|
||||||
export { default as FormWishlist } from './FormWishlist.vue'
|
export { default as FormWishlist } from './FormWishlist.vue'
|
||||||
|
export { default as FormWishlistItem } from './FormWishlistItem.vue'
|
||||||
export { default as WishlistItem } from './WishlistItem.vue'
|
export { default as WishlistItem } from './WishlistItem.vue'
|
||||||
|
|
|
@ -45,6 +45,11 @@ const itemBought = async (item: WishlistItem): Promise<void> => {
|
||||||
item.bought = true
|
item.bought = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const itemDelete = async (item: WishlistItem): Promise<void> => {
|
||||||
|
await client.delete(`/wishlist/${item.wishlistId}/item/${item.id}`)
|
||||||
|
state.value?.items?.splice(state.value.items.indexOf(item), 1)
|
||||||
|
}
|
||||||
|
|
||||||
const filteredItems = computed(() => {
|
const filteredItems = computed(() => {
|
||||||
if (!state.value || !state.value.items) {
|
if (!state.value || !state.value.items) {
|
||||||
return []
|
return []
|
||||||
|
@ -61,6 +66,7 @@ export const useWishlistStore = () => {
|
||||||
fetch,
|
fetch,
|
||||||
update,
|
update,
|
||||||
itemBought,
|
itemBought,
|
||||||
|
itemDelete,
|
||||||
filteredItems,
|
filteredItems,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
"text": "Diese Wunschliste ist leer."
|
"text": "Diese Wunschliste ist leer."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"confirmation-modal": {
|
"modal-bought-item": {
|
||||||
"title": {
|
"title": {
|
||||||
"text": "Möchten Sie den Gegenstand von der Liste nehmen?"
|
"text": "Möchten Sie den Gegenstand von der Liste nehmen?"
|
||||||
},
|
},
|
||||||
|
@ -66,6 +66,17 @@
|
||||||
"cancel-button": {
|
"cancel-button": {
|
||||||
"text": "Nein"
|
"text": "Nein"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"modal-delete-item": {
|
||||||
|
"title": {
|
||||||
|
"text": "Möchten Sie den Gegenstand von der Liste löschen?"
|
||||||
|
},
|
||||||
|
"confirm-button": {
|
||||||
|
"text": "Ja"
|
||||||
|
},
|
||||||
|
"cancel-button": {
|
||||||
|
"text": "Nein"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -76,6 +87,9 @@
|
||||||
},
|
},
|
||||||
"bought-button": {
|
"bought-button": {
|
||||||
"text": "Gekauft"
|
"text": "Gekauft"
|
||||||
|
},
|
||||||
|
"delete-button": {
|
||||||
|
"text": "Löschen"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"wishlist-header": {
|
"wishlist-header": {
|
||||||
|
|
|
@ -53,7 +53,7 @@
|
||||||
"text": "This wishlist is empty."
|
"text": "This wishlist is empty."
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"confirmation-modal": {
|
"modal-bought-item": {
|
||||||
"title": {
|
"title": {
|
||||||
"text": "Do you want to remove the item from the list?"
|
"text": "Do you want to remove the item from the list?"
|
||||||
},
|
},
|
||||||
|
@ -66,6 +66,17 @@
|
||||||
"cancel-button": {
|
"cancel-button": {
|
||||||
"text": "No"
|
"text": "No"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"modal-delete-item": {
|
||||||
|
"title": {
|
||||||
|
"text": "Do you want to delete the item from the list?"
|
||||||
|
},
|
||||||
|
"confirm-button": {
|
||||||
|
"text": "Yes"
|
||||||
|
},
|
||||||
|
"cancel-button": {
|
||||||
|
"text": "No"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -76,6 +87,9 @@
|
||||||
},
|
},
|
||||||
"bought-button": {
|
"bought-button": {
|
||||||
"text": "Bought"
|
"text": "Bought"
|
||||||
|
},
|
||||||
|
"delete-button": {
|
||||||
|
"text": "Delete"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"wishlist-header": {
|
"wishlist-header": {
|
||||||
|
|
|
@ -3,7 +3,12 @@ import { useI18n } from 'vue-i18n'
|
||||||
import { WishlistItem as WishlistItemType } from '@/types'
|
import { WishlistItem as WishlistItemType } from '@/types'
|
||||||
import { useRoute } from 'vue-router'
|
import { useRoute } from 'vue-router'
|
||||||
import { useWishlistStore, useModal, useEditMode } from '@/composables'
|
import { useWishlistStore, useModal, useEditMode } from '@/composables'
|
||||||
import { FormWishlist, ImageTile, WishlistItem } from '@/components'
|
import {
|
||||||
|
FormWishlist,
|
||||||
|
ImageTile,
|
||||||
|
WishlistItem,
|
||||||
|
FormWishlistItem,
|
||||||
|
} from '@/components'
|
||||||
import { IconNoGift } from '../components/icons'
|
import { IconNoGift } from '../components/icons'
|
||||||
|
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
@ -11,20 +16,31 @@ const modal = useModal()
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const { isActive: editModeIsActive } = useEditMode()
|
const { isActive: editModeIsActive } = useEditMode()
|
||||||
|
|
||||||
const { state, fetch, isReady, itemBought, filteredItems } = useWishlistStore()
|
const { state, fetch, isReady, itemBought, itemDelete, filteredItems } =
|
||||||
|
useWishlistStore()
|
||||||
await fetch(route.params.slug as string)
|
await fetch(route.params.slug as string)
|
||||||
|
|
||||||
const bought = async (item: WishlistItemType): Promise<void> => {
|
const bought = async (item: WishlistItemType): Promise<void> => {
|
||||||
const confirmed = await modal.show(
|
const confirmed = await modal.show(
|
||||||
t('pages.detail-view.confirmation-modal.title.text'),
|
t('pages.detail-view.modal-bought-item.title.text'),
|
||||||
t('pages.detail-view.confirmation-modal.confirm-button.text'),
|
t('pages.detail-view.modal-bought-item.confirm-button.text'),
|
||||||
t('pages.detail-view.confirmation-modal.cancel-button.text'),
|
t('pages.detail-view.modal-bought-item.cancel-button.text'),
|
||||||
t('pages.detail-view.confirmation-modal.body.text')
|
t('pages.detail-view.modal-bought-item.body.text')
|
||||||
)
|
)
|
||||||
if (confirmed) {
|
if (confirmed) {
|
||||||
itemBought(item)
|
itemBought(item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const deleteItem = async (item: WishlistItemType): Promise<void> => {
|
||||||
|
const confirmed = await modal.show(
|
||||||
|
t('pages.detail-view.modal-delete-item.title.text'),
|
||||||
|
t('pages.detail-view.modal-delete-item.confirm-button.text'),
|
||||||
|
t('pages.detail-view.modal-delete-item.cancel-button.text')
|
||||||
|
)
|
||||||
|
if (confirmed) {
|
||||||
|
itemDelete(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
@ -50,13 +66,11 @@ const bought = async (item: WishlistItemType): Promise<void> => {
|
||||||
>
|
>
|
||||||
<div v-for="(item, index) in filteredItems" :key="index">
|
<div v-for="(item, index) in filteredItems" :key="index">
|
||||||
<WishlistItem
|
<WishlistItem
|
||||||
|
v-if="!editModeIsActive"
|
||||||
:item="item"
|
:item="item"
|
||||||
:title="item.title"
|
|
||||||
:url="item.url"
|
|
||||||
:image="item.imageSrc"
|
|
||||||
:description="item.description"
|
|
||||||
@bought="bought(item)"
|
@bought="bought(item)"
|
||||||
/>
|
/>
|
||||||
|
<FormWishlistItem v-else :item="item" @delete="deleteItem(item)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-else class="flex h-1/2 w-full justify-center">
|
<div v-else class="flex h-1/2 w-full justify-center">
|
||||||
|
|
Loading…
Add table
Reference in a new issue