294 lines
7.2 KiB
Vue
294 lines
7.2 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'
|
|
import DateWidget from './DateWidget.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 left-panel">
|
|
<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 clickable" @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' : ''">
|
|
<div
|
|
class="bigiconcontainer"
|
|
:class="
|
|
data.wantread ? 'has-text-dark has-background-text border-radius-wantread-fill' : ''
|
|
"
|
|
>
|
|
<BigIcon
|
|
icon="BIconEye"
|
|
:legend="$t('bookform.wantread')"
|
|
:isSet="data.wantread"
|
|
@click="onWantReadIconClick"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="bigiconcontainer is-hidden-desktop"
|
|
:class="isStartReadExpanded() ? 'has-text-dark has-background-text' : ''"
|
|
>
|
|
<BigIcon
|
|
icon="BIconBook"
|
|
:legend="$t('bookform.wantread')"
|
|
:is-set="isStartReadExpanded()"
|
|
:is-readonly="data.read"
|
|
@click="data.read ? null : onStartReadIconClick()"
|
|
/>
|
|
</div>
|
|
<div
|
|
class="bigiconcontainer is-hidden-desktop"
|
|
:class="data.read ? 'has-text-dark has-background-text border-radius-right-fill' : ''"
|
|
>
|
|
<BigIcon
|
|
icon="BIconCheckCircle"
|
|
:legend="$t('bookform.read')"
|
|
:isSet="data.read"
|
|
@click="onReadIconClick"
|
|
/>
|
|
</div>
|
|
<BookDateWidget
|
|
class="is-hidden-mobile"
|
|
icon="BIconBook"
|
|
:legend="$t('bookform.startread')"
|
|
:start-read-date="data.startReadDate"
|
|
:is-expanded="isStartReadExpanded()"
|
|
:is-readonly="data.read"
|
|
@onStartDateChange="onStartReadDateChange"
|
|
@onIconClick="onStartReadIconClick"
|
|
/>
|
|
<BookDateWidget
|
|
class="is-hidden-mobile"
|
|
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 class="mobile-dates pt-3 is-hidden-desktop">
|
|
<div class="mobiledate">
|
|
<DateWidget
|
|
v-if="isStartReadExpanded() || data.read"
|
|
dateinputid="startread"
|
|
dateinputlabel="bookdatewidget.started"
|
|
:initdate="data.startReadDate"
|
|
is-horizontal
|
|
@onDateChange="(d) => onStartReadDateChange(d)"
|
|
/>
|
|
</div>
|
|
<div class="mobiledate pt-2">
|
|
<DateWidget
|
|
v-if="data.read"
|
|
dateinputid="endread"
|
|
dateinputlabel="bookdatewidget.finished"
|
|
:initdate="data.endReadDate"
|
|
is-horizontal
|
|
@onDateChange="(d) => onEndReadDateChange(d)"
|
|
/>
|
|
</div>
|
|
</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;
|
|
}
|
|
|
|
.mobile-dates {
|
|
display: block;
|
|
}
|
|
|
|
.mobiledate {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
@media (min-width: 1024px) {
|
|
.left-panel {
|
|
margin-left: 3rem;
|
|
}
|
|
|
|
.border-radius-wantread-fill {
|
|
border-radius: 45px 45px 0px 0px;
|
|
}
|
|
|
|
.remove-border-bottom {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.bigiconcontainer {
|
|
display: flex;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
img {
|
|
max-height: 250px;
|
|
max-width: 250px;
|
|
padding: 20px;
|
|
}
|
|
|
|
.bigiconcontainer {
|
|
flex: 1;
|
|
}
|
|
|
|
.border-radius-wantread-fill {
|
|
border-radius: 38px 0px 0px 38px;
|
|
}
|
|
|
|
.image {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.iconscontainer {
|
|
display: flex;
|
|
width: 100%;
|
|
}
|
|
|
|
.border-radius-right-fill {
|
|
border-radius: 0px 38px 38px 0px;
|
|
}
|
|
}
|
|
</style>
|