added rating books
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
import { computed } from 'vue'
|
||||
import { useRouter } from 'vue-router'
|
||||
import { getImagePathOrDefault } from './api.js'
|
||||
import { VRating } from 'vuetify/components/VRating';
|
||||
|
||||
const props = defineProps({
|
||||
id: Number,
|
||||
@@ -31,7 +32,15 @@ function openBook() {
|
||||
<div class="media-content">
|
||||
<div class="is-size-4">{{title}}</div>
|
||||
<div class="is-size-5 is-italic">{{author}}</div>
|
||||
<p>{{rating}}/10</p>
|
||||
|
||||
<VRating
|
||||
half-increments
|
||||
readonly
|
||||
:length="5"
|
||||
size="medium"
|
||||
:model-value="rating/2"
|
||||
active-color="bulma-body-color"
|
||||
/>
|
||||
</div>
|
||||
<nav v-if="read" class="level">
|
||||
<div class="level-left">
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script setup>
|
||||
import { computed } from 'vue'
|
||||
import { getBook, getImagePathOrDefault } from './api.js'
|
||||
import { getBook, getImagePathOrDefault, putBookUpdate } from './api.js'
|
||||
import { onBeforeRouteUpdate } from 'vue-router'
|
||||
import { VRating } from 'vuetify/components/VRating';
|
||||
|
||||
const props = defineProps({
|
||||
id: String
|
||||
@@ -15,6 +16,11 @@
|
||||
error = res.error;
|
||||
})
|
||||
|
||||
function onRatingUpdate(rating) {
|
||||
data.value.rating = rating * 2
|
||||
putBookUpdate(props.id, {rating: data.value.rating})
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
@@ -22,9 +28,21 @@
|
||||
<div v-if="data">
|
||||
<h3 class="title">{{data.title}}</h3>
|
||||
<h3 class="subtitle">{{data.author}}</h3>
|
||||
<figure class="image">
|
||||
<img v-bind:src="imagePathOrDefault" v-bind:alt="data.title">
|
||||
</figure>
|
||||
<div class="imagewithrating">
|
||||
<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"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -35,4 +53,10 @@ img {
|
||||
height:auto;
|
||||
width:auto;
|
||||
}
|
||||
|
||||
.imagewithrating {
|
||||
vertical-align: top;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { postReadBook, getImagePathOrDefault } from './api.js'
|
||||
import { putReadBook, getImagePathOrDefault } from './api.js'
|
||||
import { useRouter } from 'vue-router'
|
||||
|
||||
const router = useRouter();
|
||||
@@ -16,7 +16,7 @@
|
||||
const error = ref(null)
|
||||
|
||||
async function onUserBookRead() {
|
||||
const res = await postReadBook({bookId: props.id});
|
||||
const res = await putReadBook(props.id);
|
||||
if (res.ok) {
|
||||
router.push('/books')
|
||||
} else {
|
||||
|
||||
@@ -42,11 +42,15 @@ export function getBook(id) {
|
||||
}
|
||||
|
||||
export function postBook(book) {
|
||||
return genericPostCall('/book', book.value)
|
||||
return genericPayloadCall('/book', book.value, 'POST')
|
||||
}
|
||||
|
||||
export async function postReadBook(userbook) {
|
||||
return genericPostCall('/book/read', userbook)
|
||||
export async function putReadBook(bookId) {
|
||||
return putBookUpdate(bookId, {read: true})
|
||||
}
|
||||
|
||||
export async function putBookUpdate(bookId, payload) {
|
||||
return genericPayloadCall('/book/' + bookId, payload, 'PUT')
|
||||
}
|
||||
|
||||
export function postLogin(user) {
|
||||
@@ -84,12 +88,12 @@ export function genericPostCallNoAuth(apiRoute, object) {
|
||||
})
|
||||
}
|
||||
|
||||
export function genericPostCall(apiRoute, object) {
|
||||
export function genericPayloadCall(apiRoute, object, method) {
|
||||
const { user } = useAuthStore();
|
||||
|
||||
if (user != null) {
|
||||
return fetch(baseUrl + apiRoute, {
|
||||
method: 'POST',
|
||||
method: method,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer ' + user.token
|
||||
|
||||
@@ -2,7 +2,10 @@ import { createApp } from 'vue'
|
||||
import { createI18n } from "vue-i18n";
|
||||
import { createPinia } from 'pinia'
|
||||
import { BootstrapIconsPlugin } from "bootstrap-icons-vue";
|
||||
import { router } from './router.js'
|
||||
import { router } from './router.js';
|
||||
import { createVuetify } from 'vuetify'
|
||||
import { aliases, mdi } from 'vuetify/iconsets/mdi-svg'
|
||||
import { VRating } from 'vuetify/components/VRating';
|
||||
import App from './App.vue'
|
||||
|
||||
import fr from './locales/fr.json';
|
||||
@@ -17,6 +20,18 @@ const i18n = createI18n({
|
||||
});
|
||||
|
||||
|
||||
const vuetify = createVuetify({
|
||||
VRating,
|
||||
icons: {
|
||||
defaultSet: 'mdi',
|
||||
aliases,
|
||||
sets: {
|
||||
mdi,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const pinia = createPinia()
|
||||
|
||||
createApp(App).use(i18n).use(pinia).use(BootstrapIconsPlugin).use(router).mount('#app')
|
||||
|
||||
createApp(App).use(i18n).use(vuetify).use(pinia).use(BootstrapIconsPlugin).use(router).mount('#app')
|
||||
|
||||
Reference in New Issue
Block a user