add end read date
This commit is contained in:
@@ -4,17 +4,19 @@
|
||||
const props = defineProps({
|
||||
icon: String,
|
||||
legend: String,
|
||||
isSet: Boolean
|
||||
isSet: Boolean,
|
||||
isReadonly: Boolean
|
||||
});
|
||||
|
||||
const hovered = ref(false)
|
||||
|
||||
const computedIcon = computed(() => props.icon + (hovered.value || props.isSet ? "Fill" : ""));
|
||||
const computedIcon = computed(() => props.icon + (!props.isReadonly && (hovered.value || props.isSet) ? "Fill" : ""));
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="bigiconandlegend"
|
||||
:class="props.isReadonly ? '' : 'showcanclick'"
|
||||
@mouseover="hovered = true"
|
||||
@mouseout="hovered = false">
|
||||
<span class="bigicon" :title="props.legend">
|
||||
@@ -31,7 +33,7 @@
|
||||
margin:25px;
|
||||
}
|
||||
|
||||
.bigiconandlegend:hover {
|
||||
.showcanclick:hover {
|
||||
transform: scale(1.03);
|
||||
transition: ease-in-out 0.02s;
|
||||
cursor: pointer;
|
||||
|
||||
113
front/src/BookDateWidget.vue
Normal file
113
front/src/BookDateWidget.vue
Normal file
@@ -0,0 +1,113 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import BigIcon from './BigIcon.vue';
|
||||
|
||||
const props = defineProps({
|
||||
icon: String,
|
||||
legend: String,
|
||||
startReadDate: String,
|
||||
endReadDate: String,
|
||||
isExpanded: Boolean,
|
||||
isReadonly: Boolean,
|
||||
useEndDate: Boolean,
|
||||
lastWidget: Boolean
|
||||
});
|
||||
defineEmits(['onIconClick', 'onStartDateChange', 'onEndDateChange'])
|
||||
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
|
||||
function computeParentClasses() {
|
||||
let classNames = "bookdatewidget";
|
||||
if (props.isExpanded) {
|
||||
classNames += " has-text-dark has-background-text";
|
||||
}
|
||||
if (props.lastWidget) {
|
||||
classNames += " border-radius-right-and-left";
|
||||
} else {
|
||||
classNames += " border-radius-right";
|
||||
}
|
||||
if (props.isReadonly) {
|
||||
classNames += " widget-readonly"
|
||||
}
|
||||
return classNames;
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="computeParentClasses()">
|
||||
<BigIcon :icon="props.icon"
|
||||
:is-readonly="props.isReadonly"
|
||||
:legend="props.legend"
|
||||
:isSet="props.isExpanded"
|
||||
@click="props.isReadonly ? null : $emit('onIconClick') "/>
|
||||
<div v-if="props.isExpanded" class="inputdate">
|
||||
<div class="ontopofinput">
|
||||
<label class="datelabel" for="startread">
|
||||
{{$t('bookdatewidget.started')}}
|
||||
</label>
|
||||
<input class="datepicker has-background-dark has-text-light"
|
||||
id="startread"
|
||||
type="date"
|
||||
@change="(e) => $emit('onStartDateChange', e.target.value)"
|
||||
:value="props.startReadDate"
|
||||
:max="today"/>
|
||||
<div v-if="props.useEndDate">
|
||||
<label class="datelabel" for="endread">
|
||||
{{$t('bookdatewidget.finished')}}
|
||||
</label>
|
||||
<input class="datepicker has-background-dark has-text-light"
|
||||
id="endread"
|
||||
type="date"
|
||||
@change="(e) => $emit('onEndDateChange', e.target.value)"
|
||||
:value="props.endReadDate"
|
||||
:max="today"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.inputdate {
|
||||
display: flex;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
padding: 20px;
|
||||
}
|
||||
.bookdatewidget {
|
||||
display: flex;
|
||||
width: 500px;
|
||||
}
|
||||
|
||||
.border-radius-right {
|
||||
border-radius: 0 30px 30px 0;
|
||||
}
|
||||
|
||||
.border-radius-right-and-left {
|
||||
border-radius: 0 30px 30px 45px;
|
||||
}
|
||||
|
||||
.ontopofinput {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.datelabel {
|
||||
display: flex;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
font-size: 26px;
|
||||
border: none;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.datepicker {
|
||||
font-size: 26px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
|
||||
.widget-readonly {
|
||||
opacity: 50%;
|
||||
}
|
||||
</style>
|
||||
@@ -2,15 +2,16 @@
|
||||
|
||||
import { ref, computed } from 'vue'
|
||||
import { getBook, getImagePathOrDefault, putReadBook, putWantReadBook, putRateBook,
|
||||
putStartReadDate, putStartReadDateUnset } from './api.js'
|
||||
putStartReadDate, putStartReadDateUnset, putEndReadDate, putEndReadDateUnset, putUnreadBook } from './api.js'
|
||||
import { onBeforeRouteUpdate } from 'vue-router'
|
||||
import { VRating } from 'vuetify/components/VRating';
|
||||
import BigIcon from './BigIcon.vue';
|
||||
import StartReadWidget from './StartReadWidget.vue';
|
||||
import BookDateWidget from './BookDateWidget.vue';
|
||||
|
||||
const props = defineProps({
|
||||
id: String
|
||||
});
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
|
||||
let data = ref(null);
|
||||
let error = ref(null);
|
||||
@@ -34,8 +35,11 @@
|
||||
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);
|
||||
}
|
||||
putReadBook(props.id, {read: data.value.read});
|
||||
}
|
||||
|
||||
function onWantReadIconClick() {
|
||||
@@ -45,7 +49,7 @@
|
||||
|
||||
function onStartReadIconClick() {
|
||||
if (!data.value.startReadDate) {
|
||||
data.value.startReadDate = new Date().toISOString().slice(0, 10);
|
||||
data.value.startReadDate = today;
|
||||
putStartReadDate(props.id, data.value.startReadDate);
|
||||
} else {
|
||||
data.value.startReadDate = null;
|
||||
@@ -55,7 +59,26 @@
|
||||
|
||||
function onStartReadDateChange(d) {
|
||||
data.value.startReadDate = d;
|
||||
putStartReadDate(props.id, data.value.startReadDate);
|
||||
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;
|
||||
}
|
||||
|
||||
</script>
|
||||
@@ -85,20 +108,30 @@
|
||||
<p>{{data.summary}}</p>
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="iconscontainer">
|
||||
<div class="iconscontainer" :class="data.read ? 'remove-border-bottom' : ''">
|
||||
<BigIcon icon="BIconEye"
|
||||
:legend="$t('bookform.wantread')"
|
||||
:isSet="data.wantread"
|
||||
@click="onWantReadIconClick"/>
|
||||
<StartReadWidget
|
||||
<BookDateWidget
|
||||
icon="BIconBook"
|
||||
:legend="$t('bookform.startread')"
|
||||
:startReadDate="data.startReadDate"
|
||||
@onDateChange="onStartReadDateChange"
|
||||
:start-read-date="data.startReadDate"
|
||||
:is-expanded="isStartReadExpanded()"
|
||||
:is-readonly="data.read"
|
||||
@onStartDateChange="onStartReadDateChange"
|
||||
@onIconClick="onStartReadIconClick"/>
|
||||
<BigIcon icon="BIconCheckCircle"
|
||||
<BookDateWidget
|
||||
icon="BIconCheckCircle"
|
||||
:legend="$t('bookform.read')"
|
||||
:isSet="data.read"
|
||||
@click="onReadIconClick"/>
|
||||
: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>
|
||||
@@ -124,5 +157,9 @@ img {
|
||||
width: 250px;
|
||||
}
|
||||
|
||||
.remove-border-bottom {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
const error = ref(null)
|
||||
|
||||
async function onUserBookRead() {
|
||||
const res = await putReadBook(props.id, {read: true});
|
||||
const res = await putReadBook(props.id);
|
||||
if (res.ok) {
|
||||
router.push('/books')
|
||||
} else {
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import BigIcon from './BigIcon.vue';
|
||||
|
||||
const props = defineProps({
|
||||
legend: String,
|
||||
startReadDate: String
|
||||
});
|
||||
defineEmits(['onIconClick', 'onDateChange'])
|
||||
|
||||
const today = new Date().toISOString().slice(0, 10);
|
||||
|
||||
function computeParentClasses() {
|
||||
if (props.startReadDate) {
|
||||
return "startdatewidget has-text-dark has-background-text"
|
||||
} else {
|
||||
return "startdatewidget"
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div :class="computeParentClasses()">
|
||||
<BigIcon icon="BIconBook"
|
||||
:legend="props.legend"
|
||||
:isSet="props.startReadDate ? true : false"
|
||||
@click="$emit('onIconClick')"/>
|
||||
<div v-if="props.startReadDate" class="inputdate">
|
||||
<div class="ontopofinput">
|
||||
<label class="datelabel" for="startread">
|
||||
{{$t('startreadwidget.started')}}
|
||||
</label>
|
||||
<input class="datepicker has-background-dark has-text-light"
|
||||
id="startread"
|
||||
type="date"
|
||||
@change="(e) => $emit('onDateChange', e.target.value)"
|
||||
:value="props.startReadDate"
|
||||
:max="today"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
|
||||
.inputdate {
|
||||
display: flex;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
padding: 20px;
|
||||
}
|
||||
.startdatewidget {
|
||||
display: flex;
|
||||
width: 500px;
|
||||
border-radius: 0 30px 30px 0;
|
||||
}
|
||||
.ontopofinput {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.datelabel {
|
||||
display: flex;
|
||||
justify-content:center;
|
||||
align-items:center;
|
||||
font-size: 26px;
|
||||
border: none;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.datepicker {
|
||||
font-size: 26px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
@@ -49,8 +49,20 @@ export function postBook(book) {
|
||||
return genericPayloadCall('/book', book.value, 'POST')
|
||||
}
|
||||
|
||||
export async function putReadBook(bookId, payload) {
|
||||
return genericPayloadCall('/book/' + bookId + "/read", payload, 'PUT')
|
||||
export async function putReadBook(bookId) {
|
||||
return genericPayloadCall('/book/' + bookId + "/read", {read: true}, 'PUT')
|
||||
}
|
||||
|
||||
export async function putUnreadBook(bookId) {
|
||||
return genericPayloadCall('/book/' + bookId + "/read", {read: false}, 'PUT')
|
||||
}
|
||||
|
||||
export async function putEndReadDate(bookId, enddate) {
|
||||
return genericPayloadCall('/book/' + bookId + "/read", {read: true, endDate: enddate}, 'PUT')
|
||||
}
|
||||
|
||||
export async function putEndReadDateUnset(bookId) {
|
||||
return genericPayloadCall('/book/' + bookId + "/read", {read: true, endDate: "null"}, 'PUT')
|
||||
}
|
||||
|
||||
export async function putStartReadDateUnset(bookId) {
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
"goto":"Goto page {pageNumber}",
|
||||
"page":"Page {pageNumber}"
|
||||
},
|
||||
"startreadwidget" :{
|
||||
"started": "Started at :"
|
||||
"bookdatewidget" :{
|
||||
"started": "Started at :",
|
||||
"finished": "Finished at :"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,8 @@
|
||||
"goto":"Aller à la page {pageNumber}",
|
||||
"page":"Page {pageNumber}"
|
||||
},
|
||||
"startreadwidget" :{
|
||||
"started": "Commencé le :"
|
||||
"bookdatewidget" :{
|
||||
"started": "Commencé le :",
|
||||
"finished": "Fini le :"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user