Files
bibliomane/front/src/BookForm.vue
Arthur Lefebvre aee6fbaf73 Book form: can now click "start read" even when the book is marked as read
It will do the same behavior as clicking on the "read" button again to
cancel it.
2026-03-08 19:00:40 +01:00

170 lines
4.0 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 BookFormIcons from './BookFormIcons.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 })
}
async 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 })
}
async function onStartReadIconClick() {
if (!data.value.startReadDate) {
data.value.startReadDate = today
putStartReadDate(props.id, data.value.startReadDate)
} else if (!data.value.read) {
data.value.startReadDate = null
putStartReadDateUnset(props.id)
}
if (data.value.read) {
data.value.read = false
putUnreadBook(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 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">
<BookFormIcons
v-bind="data"
@on-want-read-icon-click="onWantReadIconClick"
@on-start-read-icon-click="onStartReadIconClick"
@on-read-icon-click="onReadIconClick"
@on-start-read-date-change="onStartReadDateChange"
@on-end-read-date-change="onEndReadDateChange"
/>
</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;
}
@media (min-width: 1024px) {
.left-panel {
margin-left: 3rem;
}
}
@media (max-width: 1024px) {
img {
max-height: 250px;
max-width: 250px;
padding: 20px;
}
.image {
display: flex;
justify-content: center;
align-items: center;
}
}
</style>