diff --git a/src/api/config/schemas/wishlist.ts b/src/api/config/schemas/wishlist.ts index 06d7b63..f1ae3e8 100644 --- a/src/api/config/schemas/wishlist.ts +++ b/src/api/config/schemas/wishlist.ts @@ -30,6 +30,7 @@ export const wishlistRequestSchema = { required: ['title', 'imageSrc', 'slugUrlText'], properties: { title: { type: 'string' }, + public: { type: 'boolean' }, imageSrc: { type: 'string' }, description: { type: 'string' }, slugUrlText: { type: 'string' }, @@ -40,6 +41,7 @@ export const wishlistResponseSchema = { properties: { id: { type: 'string' }, title: { type: 'string' }, + public: { type: 'boolean' }, imageSrc: { type: 'string' }, description: { type: 'string' }, slugUrlText: { type: 'string' }, diff --git a/src/components/Header.vue b/src/components/Header.vue index e38d0b3..8c2a3e6 100644 --- a/src/components/Header.vue +++ b/src/components/Header.vue @@ -37,7 +37,7 @@ import { useAuth, useEditMode } from '@/composables/' const { t } = useI18n() const { isAuthenticated, setToken } = useAuth() -const { editMode, toggle } = useEditMode() +const { state: editMode, toggle } = useEditMode() const toggleDark = useToggle(useDark()) diff --git a/src/components/InputCheckbox.vue b/src/components/InputCheckbox.vue new file mode 100644 index 0000000..76ce7bc --- /dev/null +++ b/src/components/InputCheckbox.vue @@ -0,0 +1,37 @@ + + + {{ label }} + + + + + diff --git a/src/components/TextInput.vue b/src/components/InputText.vue similarity index 100% rename from src/components/TextInput.vue rename to src/components/InputText.vue diff --git a/src/components/InputTextArea.vue b/src/components/InputTextArea.vue new file mode 100644 index 0000000..4c1a63f --- /dev/null +++ b/src/components/InputTextArea.vue @@ -0,0 +1,60 @@ + + + {{ label }} + + + + {{ errorMessage }} + + + + + diff --git a/src/components/WishlistHeader.vue b/src/components/WishlistHeader.vue new file mode 100644 index 0000000..97c5663 --- /dev/null +++ b/src/components/WishlistHeader.vue @@ -0,0 +1,106 @@ + + + + + + {{ modelValue.title }} + + + {{ modelValue.description }} + + + + + + + + + {{ + t('components.wishlist-header.main.form.submit.text') + }} + + + + + diff --git a/src/composables/useEditMode.ts b/src/composables/useEditMode.ts index 5fa6bb2..b40da56 100644 --- a/src/composables/useEditMode.ts +++ b/src/composables/useEditMode.ts @@ -1,5 +1,7 @@ -import { ref, readonly } from 'vue' +import { useAuth } from './useAuth' +import { ref, readonly, computed } from 'vue' +const { isAuthenticated } = useAuth() const state = ref(false) const activate = (): void => { @@ -14,9 +16,12 @@ const toggle = (): void => { state.value = !state.value } +const isActive = computed(() => state.value && isAuthenticated.value) + export const useEditMode = () => { return { - editMode: readonly(state), + state: readonly(state), + isActive, activate, deactivate, toggle, diff --git a/src/composables/useWishlistStore.ts b/src/composables/useWishlistStore.ts index 3b288c8..f64d2a2 100644 --- a/src/composables/useWishlistStore.ts +++ b/src/composables/useWishlistStore.ts @@ -16,6 +16,25 @@ const fetch = async (slugText: string): Promise => { } } +const update = async (updatedData: Wishlist): Promise => { + const id = state.value?.id + const payload = { + ...state.value, + ...updatedData, + } + try { + const { data } = await client.put(`/wishlist/${id}`, payload) + state.value = { + ...state.value, + ...data, + } + } catch (e: any) { + if (e.isAxiosError && !(e.ignore)) { + throw e + } + } +} + const itemBought = async (item: WishlistItem): Promise => { await client.post(`/wishlist/${item.wishlistId}/item/${item.id}/bought`) item.bought = true @@ -25,6 +44,7 @@ export const useWishlistStore = () => { return { state, fetch, + update, itemBought, } } diff --git a/src/config/locales/de-DE.json b/src/config/locales/de-DE.json index 00304b9..7fbddc0 100644 --- a/src/config/locales/de-DE.json +++ b/src/config/locales/de-DE.json @@ -70,6 +70,35 @@ "text": "Gekauft" } }, + "wishlist-header": { + "main": { + "form": { + "title": { + "label": "Titel", + "error-requried": "Titel wird benötigt" + }, + "public": { + "label": "Auf der Startseite anzeigen?" + }, + "description": { + "label": "Beschreibung", + "error-max": "Die maximale Länge beträgt 300 Zeichen" + }, + "slug-text": { + "label": "URL Slug-Text", + "error-requried": "URL Slug-Text wird benötigt" + }, + "image-src": { + "label": "Bild-URL", + "error-requried": "Bild-URL wird benötigt", + "error-url": "Bild-URL muss eine gültige URL sein" + }, + "submit": { + "text": "Speichern" + } + } + } + }, "header": { "edit-mode": { "text": "Bearbeitungsmodus" diff --git a/src/config/locales/en-US.json b/src/config/locales/en-US.json index 41ff6fb..16c2fd4 100644 --- a/src/config/locales/en-US.json +++ b/src/config/locales/en-US.json @@ -70,6 +70,33 @@ "text": "Bought" } }, + "wishlist-header": { + "main": { + "form": { + "title": { + "label": "Title" + }, + "public": { + "label": "Show on startpage?" + }, + "description": { + "label": "Description", + "error-max": "The max. length is 300 chars." + }, + "slug-text": { + "label": "URL Slug-Text" + }, + "image-src": { + "label": "Image-URL", + "error-requried": "Image-URL is required", + "error-url": "Image-URL has to be a valid url" + }, + "submit": { + "text": "Save" + } + } + } + }, "header": { "edit-mode": { "text": "Edit-Mode" diff --git a/src/views/DetailView.vue b/src/views/DetailView.vue index 6a1ffe5..4ff5a83 100644 --- a/src/views/DetailView.vue +++ b/src/views/DetailView.vue @@ -4,8 +4,8 @@ import { WishlistItem as WishlistItemType } from '@/types' import { computed } from 'vue' import { useRoute } from 'vue-router' import { useWishlistStore, useModal } from '@/composables' -import ImageTile from '@/components/ImageTile.vue' import WishlistItem from '@/components/WishlistItem.vue' +import WishlistHeader from '@/components/WishlistHeader.vue' import { IconNoGift } from '../components/icons' const route = useRoute() @@ -37,19 +37,7 @@ const bought = async (item: WishlistItemType): Promise => { - - - - - {{ state.title }} - - - {{ state.description }} - - - + { v-slot="{ meta }" class="w-full flex-col space-y-3" > -
+ {{ errorMessage }} +
+ {{ modelValue.description }} +
- {{ state.description }} -