feat: Multiple Systems

This commit is contained in:
2024-03-18 01:26:54 +01:00
parent 22ea1930c4
commit 12d8f3913c
29 changed files with 2556 additions and 90 deletions

View File

@@ -0,0 +1,58 @@
<script setup lang="ts">
import { useBookRecommendationStore } from '~/stores/book-recommendations'
const props = defineProps<{
row: {
id: number
book_name: string
}
}>()
const isOpen = ref(false)
const authStore = useAuthStore()
const state = reactive({
book_recommendation_id: props.row.id,
})
const bookRecommendationStore = useBookRecommendationStore()
const { refresh: onVote, status } = useFetch<any>(`vote`, {
method: 'POST',
body: state,
immediate: false,
watch: false,
async onResponse({ response }) {
if (response.ok) {
useToast().add({
icon: 'i-heroicons-check-circle-20-solid',
title: 'Abstimmung erfolgreich.',
color: 'emerald',
})
await bookRecommendationStore.fetchRecommendations()
await authStore.fetchUser()
isOpen.value = false
}
},
})
</script>
<template>
<UButton icon="i-heroicons-star" size="sm" color="green" variant="solid" square :disabled="authStore.user.total_votes === 0" @click="isOpen = true" />
<UDashboardModal
v-model="isOpen"
title="Buch Empfehlung löschen"
:description="`Bist du dir sicher das du für die Buchempfehlung ${row.book_name} abstimmen möchtest?`"
icon="i-heroicons-star"
:ui="{
icon: { base: 'text-green-500 dark:text-green-400' } as any,
footer: { base: 'ml-16' } as any,
}"
>
<template #footer>
<UButton color="primary" label="Abstimmung" :loading="status === 'pending'" @click="onVote" />
<UButton color="white" label="Abbrechen" @click="isOpen = false" />
</template>
</UDashboardModal>
</template>

View File

@@ -0,0 +1,50 @@
<script setup lang="ts">
import { useBookRecommendationStore } from '~/stores/book-recommendations'
const props = defineProps<{
row: {
id: number
book_name: string
}
}>()
const isOpen = ref(false)
const bookRecommendationStore = useBookRecommendationStore()
const { refresh: onDelete, status } = useFetch<any>(`book-recommendations/${props.row.id}`, {
method: 'DELETE',
immediate: false,
watch: false,
async onResponse({ response }) {
if (response.ok) {
useToast().add({
icon: 'i-heroicons-check-circle-20-solid',
title: 'Buchempfehlung wurde gelöscht.',
color: 'emerald',
})
await bookRecommendationStore.fetchRecommendations()
}
isOpen.value = false
},
})
</script>
<template>
<UButton icon="i-heroicons-trash" size="sm" color="red" variant="solid" square @click="isOpen = true" />
<UDashboardModal
v-model="isOpen"
title="Buch Empfehlung löschen"
:description="`Möchtest du die Buchempfehlung ${row.book_name} wirklich löschen?`"
icon="i-heroicons-exclamation-circle"
:ui="{
icon: { base: 'text-red-500 dark:text-red-400' } as any,
footer: { base: 'ml-16' } as any,
}"
>
<template #footer>
<UButton color="red" label="Löschen" :loading="status === 'pending'" @click="onDelete" />
<UButton color="white" label="Abbrechen" @click="isOpen = false" />
</template>
</UDashboardModal>
</template>

View File

@@ -0,0 +1,97 @@
<script setup lang="ts">
import { useBookRecommendationStore } from '~/stores/book-recommendations'
const props = defineProps<{
row: {
id: number
book_name: string
author: string
description: string
isbn: string
pages: number
cover_image?: string
status: string
}
}>()
const isOpen = ref(false)
const form = ref()
const state = reactive({
book_name: props.row.book_name,
author: props.row.author,
description: props.row.description,
isbn: props.row.isbn,
pages: props.row.pages,
cover_image: props.row.cover_image,
status: props.row.status,
})
const bookRecommendationStore = useBookRecommendationStore()
const { refresh: onSubmit, status } = useFetch<any>(`book-recommendations/${props.row.id}`, {
method: 'PUT',
body: state,
immediate: false,
watch: false,
async onResponse({ response }) {
if (response?.status === 422) {
form.value.setErrors(response._data?.errors)
}
else if (response.ok) {
useToast().add({
icon: 'i-heroicons-check-circle-20-solid',
title: 'Buchempfehlung wurde erfolgreich aktualisiert.',
color: 'emerald',
})
await bookRecommendationStore.fetchRecommendations()
isOpen.value = false
}
},
})
</script>
<template>
<div>
<UButton icon="i-heroicons-pencil-square" size="sm" variant="solid" square @click="isOpen = true" />
<UModal v-model="isOpen">
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
<template #header>
<div class="flex items-center justify-between">
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
Bearbeiten
</h3>
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="isOpen = false" />
</div>
</template>
<UForm ref="form" :state="state" class="space-y-4" @submit="onSubmit">
<UFormGroup label="Name" name="book_name">
<UInput v-model="state.book_name" />
</UFormGroup>
<UFormGroup label="Autor" name="author">
<UInput v-model="state.author" />
</UFormGroup>
<UFormGroup label="Beschreibung" name="description">
<UTextarea v-model="state.description" />
</UFormGroup>
<UFormGroup label="ISBN" name="isbn">
<UInput v-model="state.isbn" />
</UFormGroup>
<UFormGroup label="Seiten" name="pages">
<UInput v-model="state.pages" type="number" />
</UFormGroup>
<UFormGroup label="Status" name="status">
<USelect v-model="state.status" :options="bookRecommendationStore.statusOptions" option-attribute="name" />
</UFormGroup>
<UButton size="md" type="submit" :loading="status === 'pending'">
Speichern
</UButton>
<UButton size="md" class="mx-4" color="white" label="Abbrechen" @click="isOpen = false" />
</UForm>
</UCard>
</UModal>
</div>
</template>

View File

@@ -0,0 +1,95 @@
<script setup lang="ts">
import { useBookRecommendationStore } from '~/stores/book-recommendations'
const isOpen = ref(false)
const form = ref()
const state = reactive({
book_name: null,
author: null,
description: null,
isbn: null,
pages: null,
cover_image: null,
status: null,
})
const bookRecommendationStore = useBookRecommendationStore()
const { refresh: onSubmit, status } = useFetch<any>(`book-recommendations`, {
method: 'POST',
body: state,
immediate: false,
watch: false,
async onResponse({ response }) {
if (response?.status === 422) {
form.value.setErrors(response._data?.errors)
}
else if (response.ok) {
useToast().add({
icon: 'i-heroicons-check-circle-20-solid',
title: 'Buchempfehlung wurde erfolgreich aktualisiert.',
color: 'emerald',
})
await bookRecommendationStore.fetchRecommendations()
state.book_name = null
state.author = null
state.description = null
state.isbn = null
state.pages = null
state.cover_image = null
state.status = null
isOpen.value = false
}
},
})
</script>
<template>
<div>
<div class="flex justify-end">
<UButton icon="i-heroicons-plus" label="Neues Buch" size="sm" variant="solid" color="green" square @click="isOpen = true" />
</div>
<UModal v-model="isOpen">
<UCard :ui="{ ring: '', divide: 'divide-y divide-gray-100 dark:divide-gray-800' }">
<template #header>
<div class="flex items-center justify-between">
<h3 class="text-base font-semibold leading-6 text-gray-900 dark:text-white">
Neues Buch
</h3>
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" class="-my-1" @click="isOpen = false" />
</div>
</template>
<UForm ref="form" :state="state" class="space-y-4" @submit="onSubmit">
<UFormGroup label="Name" name="book_name">
<UInput v-model="state.book_name" />
</UFormGroup>
<UFormGroup label="Autor" name="author">
<UInput v-model="state.author" />
</UFormGroup>
<UFormGroup label="Beschreibung" name="description">
<UTextarea v-model="state.description" />
</UFormGroup>
<UFormGroup label="ISBN" name="isbn">
<UInput v-model="state.isbn" />
</UFormGroup>
<UFormGroup label="Seiten" name="pages">
<UInput v-model="state.pages" type="number" />
</UFormGroup>
<UFormGroup label="Status" name="status">
<USelect v-model="state.status" :options="bookRecommendationStore.statusOptions" option-attribute="name" />
</UFormGroup>
<UButton size="md" type="submit" :loading="status === 'pending'">
Erstellen
</UButton>
<UButton size="md" class="mx-4" color="white" label="Abbrechen" @click="isOpen = false" />
</UForm>
</UCard>
</UModal>
</div>
</template>