95 lines
2.1 KiB
Vue
95 lines
2.1 KiB
Vue
<script setup>
|
|
import { ref, computed } from 'vue'
|
|
import { getSearchBooks, postCollectionAddBook, extractFormErrorFromField } from './api.js'
|
|
|
|
const props = defineProps({
|
|
collectionId: Number,
|
|
})
|
|
|
|
const emit = defineEmits(['created'])
|
|
|
|
const book = ref({
|
|
id: 0,
|
|
title: '',
|
|
})
|
|
const addingBook = ref(false)
|
|
const data = ref(null)
|
|
const error = ref(null)
|
|
const titleError = computed(() => {
|
|
return extractFormErrorFromField('Title', error.value)
|
|
})
|
|
const vFocus = {
|
|
mounted: (el) => el.focus(),
|
|
}
|
|
|
|
const limit = 5
|
|
|
|
function fetchBooks() {
|
|
if (!book || book.value.title.length < 3) {
|
|
return
|
|
}
|
|
const lang = navigator.language.substring(0, 2)
|
|
getSearchBooks(data, error, book.value.title, lang, 0, limit, 0)
|
|
}
|
|
|
|
function addBook(bookId) {
|
|
postCollectionAddBook(props.collectionId, bookId).then((res) => {
|
|
if (res.ok) {
|
|
addingBook.value = false
|
|
book.value.id = 0
|
|
book.value.title = ''
|
|
data.value = null
|
|
error.value = null
|
|
emit('created')
|
|
} else {
|
|
res.json().then((json) => {
|
|
error.value = json
|
|
})
|
|
}
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<div class="field has-addons">
|
|
<div v-if="addingBook" class="control">
|
|
<input
|
|
:class="'input is-large ' + (titleError ? 'is-danger' : '')"
|
|
v-focus
|
|
@keyup="fetchBooks()"
|
|
type="text"
|
|
maxlength="300"
|
|
v-model="book.title"
|
|
:placeholder="$t('inputbookwidget.searchinput')"
|
|
/>
|
|
<p v-if="titleError" class="help is-danger">{{ titleError }}</p>
|
|
<ul v-if="data" class="popupresults has-background-dark">
|
|
<li v-for="book in data.books" @click="addBook(book.id)" class="bookresult p-2">
|
|
{{ book.title }}
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div v-if="!addingBook" class="control">
|
|
<button @click="addingBook = true" class="button is-large mb-2">
|
|
<span class="icon" :title="$t('collections.add')">
|
|
<b-icon-plus />
|
|
</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.popupresults {
|
|
z-index: 999;
|
|
}
|
|
|
|
.bookresult {
|
|
cursor: pointer;
|
|
}
|
|
|
|
.bookresult:hover {
|
|
background-color: var(--bulma-text-40);
|
|
}
|
|
</style>
|