64 lines
2.1 KiB
Vue
64 lines
2.1 KiB
Vue
<script setup lang="ts">
|
|
import type { FormSubmitEvent } from '@nuxt/ui'
|
|
|
|
const emit = defineEmits<{ saved: [] }>()
|
|
|
|
const { data: books, status } = useFetch<DiaryBook[]>('/api/diary/books', { key: 'diary-books', default: () => [], lazy: true })
|
|
|
|
// Recently read books first, then the rest by title
|
|
const bookItems = computed(() => books.value
|
|
.toSorted((a, b) => (b.readDate ?? '').localeCompare(a.readDate ?? '') || a.title.localeCompare(b.title, 'de'))
|
|
.map(book => ({
|
|
label: book.title,
|
|
description: book.authors.join('; '),
|
|
originalTitle: book.originalTitle,
|
|
value: book.id
|
|
})))
|
|
|
|
const state = reactive({ bookId: undefined as number | undefined, date: todayIso(), text: '' })
|
|
const { saving, save } = useSaveEntry({
|
|
url: '/api/diary/reviews',
|
|
dataKey: ['diary-reviews', 'diary-books'],
|
|
saved: 'Rezension gespeichert',
|
|
failed: 'Rezension konnte nicht gespeichert werden',
|
|
onSaved: () => emit('saved')
|
|
})
|
|
|
|
watch(() => state.bookId, (id) => {
|
|
state.date = books.value.find(book => book.id === id)?.readDate ?? todayIso()
|
|
})
|
|
|
|
function onSubmit(event: FormSubmitEvent<NewReviewInput>) {
|
|
return save(event.data)
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<UForm :schema="newReviewSchema" :state="state" class="space-y-5" @submit="onSubmit">
|
|
<UFormField label="Buch" name="bookId" required>
|
|
<USelectMenu
|
|
v-model="state.bookId"
|
|
:items="bookItems"
|
|
value-key="value"
|
|
:filter-fields="['label', 'description', 'originalTitle']"
|
|
:loading="status === 'pending'"
|
|
:search-input="{ placeholder: 'Titel oder Autor' }"
|
|
placeholder="Buch auswählen"
|
|
icon="i-lucide-book-open"
|
|
virtualize
|
|
class="w-full"
|
|
/>
|
|
</UFormField>
|
|
|
|
<UFormField label="Gelesen am" name="date" help="Wird als Lesedatum des Buchs gespeichert" required>
|
|
<UInput v-model="state.date" type="date" />
|
|
</UFormField>
|
|
|
|
<UFormField label="Rezension" name="text" required>
|
|
<UTextarea v-model="state.text" :rows="8" autoresize :maxrows="18" class="w-full" />
|
|
</UFormField>
|
|
|
|
<UButton type="submit" label="Rezension speichern" :icon="REVIEW_ICON" :loading="saving" />
|
|
</UForm>
|
|
</template>
|