diff --git a/src/components/FormWishlistItem.vue b/src/components/FormWishlistItem.vue index 32df92c..2100445 100644 --- a/src/components/FormWishlistItem.vue +++ b/src/components/FormWishlistItem.vue @@ -7,14 +7,14 @@ :src="item.imageSrc" :alt="item.title" /> - <div class="flex w-full flex-col justify-between space-y-2 p-2"> - <Form - @submit="onSubmit" - :validation-schema="schema" - v-slot="{ meta }" - class="w-full flex-col" - > + <h1 v-if="mode === 'create'" class="text-xl"> + {{ t('components.form-wishlist-item.headline-new-item.text') }} + </h1> + <h1 v-else class="text-xl"> + {{ t('components.form-wishlist-item.headline-change-item.text') }} + </h1> + <form @submit="onSubmit" class="w-full flex-col"> <InputText name="title" type="text" @@ -41,6 +41,7 @@ :label="t('components.form-wishlist-item.image-src.label')" /> <InputCheckbox + v-if="mode === 'update'" name="bought" :value="item.bought" :label="t('components.form-wishlist-item.bought.label')" @@ -52,8 +53,9 @@ :icon="IconSave" >{{ t('components.form-wishlist-item.submit.text') }}</ButtonBase > - </Form> + </form> <ButtonBase + v-if="mode === 'update'" class="h-12 w-full" mode="danger" @click.prevent="() => emits('delete')" @@ -65,7 +67,7 @@ </template> <script lang="ts" setup> import { useI18n } from 'vue-i18n' -import { Form } from 'vee-validate' +import { useForm } from 'vee-validate' import ImagePreview from './ImagePreview.vue' import { object, string, boolean } from 'yup' import { @@ -76,12 +78,29 @@ import { } from '@/components' import { IconSave, IconDelete } from '@/components/icons' import { WishlistItem } from '@/types' -defineProps<{ - item: WishlistItem -}>() -const { t } = useI18n() +import { PropType } from 'vue' -const emits = defineEmits(['update', 'delete']) +const props = defineProps({ + mode: { + type: String, + required: true, + }, + item: { + type: Object as PropType<WishlistItem>, + default: () => { + return { + id: '', + title: '', + description: '', + url: '', + imageSrc: '', + bought: false, + } + }, + }, +}) +const emits = defineEmits(['update', 'create', 'delete']) +const { t } = useI18n() const schema = object({ title: string().required( @@ -97,7 +116,16 @@ const schema = object({ bought: boolean(), }) -const onSubmit = async (values: any): Promise<void> => { - emits('update', values) -} +const { handleSubmit, resetForm, meta } = useForm({ + validationSchema: schema, +}) + +const onSubmit = handleSubmit((values) => { + if (props.mode === 'create') { + emits('create', values) + resetForm() + } else { + emits('update', values) + } +}) </script> diff --git a/src/composables/useWishlistStore.ts b/src/composables/useWishlistStore.ts index 81823b4..a6fec72 100644 --- a/src/composables/useWishlistStore.ts +++ b/src/composables/useWishlistStore.ts @@ -40,6 +40,21 @@ const update = async (updatedData: Wishlist): Promise<void> => { } } +const createItem = async (values: WishlistItem): Promise<void> => { + const id = state.value?.id + const payload = { + ...values, + } + try { + const { data } = await client.post(`/wishlist/${id}/item`, payload) + state.value?.items?.push(data) + } catch (e: any) { + if (e.isAxiosError && !(<CustomAxiosError>e.ignore)) { + throw e + } + } +} + const updateItem = async ( currentValues: WishlistItem, newValues: WishlistItem @@ -91,6 +106,7 @@ export const useWishlistStore = () => { isReady, fetch, update, + createItem, updateItem, itemBought, itemDelete, diff --git a/src/config/locales/de-DE.json b/src/config/locales/de-DE.json index 5c718b7..c702742 100644 --- a/src/config/locales/de-DE.json +++ b/src/config/locales/de-DE.json @@ -126,6 +126,12 @@ } }, "form-wishlist-item": { + "headline-new-item": { + "text": "Neuen Eintrag hinzufügen" + }, + "headline-change-item": { + "text": "Eintrag bearbeiten" + }, "title": { "label": "Titel", "error-requried": "Titel wird benötigt." diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index 3cf893d..0706bc4 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -123,6 +123,12 @@ } }, "form-wishlist-item": { + "headline-new-item": { + "text": "Add new item" + }, + "headline-change-item": { + "text": "Change item" + }, "title": { "label": "Title", "error-requried": "Title is required." diff --git a/src/views/DetailView.vue b/src/views/DetailView.vue index 80e9db4..818fa30 100644 --- a/src/views/DetailView.vue +++ b/src/views/DetailView.vue @@ -24,6 +24,7 @@ const { fetch, isReady, update, + createItem, updateItem, itemBought, itemDelete, @@ -41,6 +42,15 @@ const handleUpdateWishlist = async (wishlist: Wishlist): Promise<void> => { } } +const handleCreateItem = async (values: WishlistItemType): Promise<void> => { + try { + await createItem(values) + toast.success(t('common.saved.text')) + } catch (error) { + toast.error(t('common.saving-failed.text')) + } +} + const handleUpdateItem = async ( currentValues: WishlistItemType, newValues: WishlistItemType @@ -97,6 +107,11 @@ const handleDeleteItem = async (item: WishlistItemType): Promise<void> => { 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" @@ -106,6 +121,7 @@ const handleDeleteItem = async (item: WishlistItemType): Promise<void> => { <FormWishlistItem v-else :item="item" + mode="update" @update="(updateValues) => handleUpdateItem(item, updateValues)" @delete="handleDeleteItem(item)" />