Files
bibliomane/front/src/BookForm.vue

174 lines
4.9 KiB
Vue

<script setup>
import { ref, computed } from 'vue'
import { getBook, getImagePathOrDefault, putReadBook, putWantReadBook, putRateBook,
putStartReadDate, putStartReadDateUnset, putEndReadDate, putEndReadDateUnset, putUnreadBook } from './api.js'
import { useRouter, onBeforeRouteUpdate } from 'vue-router'
import { VRating } from 'vuetify/components/VRating';
import BigIcon from './BigIcon.vue';
import BookDateWidget from './BookDateWidget.vue';
const router = useRouter();
const props = defineProps({
id: String
});
const today = new Date().toISOString().slice(0, 10);
let data = ref(null);
let error = ref(null);
getBook(data, error, props.id);
const imagePathOrDefault = computed(() => getImagePathOrDefault(data.value.coverPath));
onBeforeRouteUpdate(async (to, from) => {
getBook(data, error, to.params.id);
})
function onRatingUpdate(rating) {
data.value.rating = rating * 2;
if (data.value.rating > 0) {
data.value.read = true;
data.value.wantread = false;
}
putRateBook(props.id, {rating: data.value.rating});
}
function onReadIconClick() {
data.value.read = !data.value.read;
if (data.value.read) {
data.value.wantread = false;
data.value.endReadDate = today;
putEndReadDate(props.id, today);
} else {
putUnreadBook(props.id);
}
}
function onWantReadIconClick() {
data.value.wantread = !data.value.wantread;
putWantReadBook(props.id, {wantread: data.value.wantread});
}
function onStartReadIconClick() {
if (!data.value.startReadDate) {
data.value.startReadDate = today;
putStartReadDate(props.id, data.value.startReadDate);
} else {
data.value.startReadDate = null;
putStartReadDateUnset(props.id);
}
}
function onStartReadDateChange(d) {
data.value.startReadDate = d;
if (d != "") {
putStartReadDate(props.id, data.value.startReadDate);
} else {
putStartReadDateUnset(props.id);
}
}
function onEndReadDateChange(d) {
data.value.endReadDate = d;
if (d != "") {
putEndReadDate(props.id, data.value.endReadDate);
} else {
putEndReadDateUnset(props.id);
}
}
function isStartReadExpanded() {
let isStartReadDateSet = data.value.startReadDate ? true : false;
let isReadUnset = !data.value.read ? true : false;
return isStartReadDateSet && isReadUnset;
}
function goToAuthor() {
router.push("/author/" + data.value.authorId)
}
</script>
<template>
<div v-if="error">{{$t('bookform.error', {error: error.message})}}</div>
<div v-if="data" class="columns">
<div class="column is-narrow ml-6">
<figure class="image">
<img v-bind:src="imagePathOrDefault" v-bind:alt="data.title">
</figure>
<VRating
half-increments
hover
:length="5"
size="x-large"
density="compact"
:model-value="data.rating/2"
@update:modelValue="onRatingUpdate"
active-color="bulma-body-color"
class="centered"
/>
</div>
<div class="column">
<h3 class="title">{{data.title}}</h3>
<h3 class="subtitle" @click="goToAuthor">{{data.author}}</h3>
<p>{{data.summary}}</p>
<div class="my-5" v-if="data.isbn">ISBN: {{data.isbn}}</div>
<div class="my-5" v-if="data.inventaireid">Inventaire ID: {{data.inventaireid}}</div>
<div class="my-5" v-if="data.openlibraryid">OLID: {{data.openlibraryid}}</div>
</div>
<div class="column">
<div class="iconscontainer" :class="data.read ? 'remove-border-bottom' : ''">
<BigIcon icon="BIconEye"
:legend="$t('bookform.wantread')"
:isSet="data.wantread"
@click="onWantReadIconClick"/>
<BookDateWidget
icon="BIconBook"
:legend="$t('bookform.startread')"
:start-read-date="data.startReadDate"
:is-expanded="isStartReadExpanded()"
:is-readonly="data.read"
@onStartDateChange="onStartReadDateChange"
@onIconClick="onStartReadIconClick"/>
<BookDateWidget
icon="BIconCheckCircle"
:legend="$t('bookform.read')"
:start-read-date="data.startReadDate"
use-end-date
last-widget
:endReadDate="data.endReadDate"
:isExpanded="data.read"
@onStartDateChange="onStartReadDateChange"
@onEndDateChange="onEndReadDateChange"
@onIconClick="onReadIconClick"/>
</div>
</div>
</div>
</template>
<style scoped>
img {
max-height:500px;
max-width:500px;
height:auto;
width:auto;
}
.centered {
display:flex;
justify-content:center;
align-items:center;
}
.iconscontainer {
border: solid;
border-radius: 50px;
width: 250px;
}
.remove-border-bottom {
border-bottom: none;
}
</style>