Skip to content

Commit

Permalink
feat: add history view
Browse files Browse the repository at this point in the history
  • Loading branch information
bayang committed May 25, 2022
1 parent 703f0a2 commit e8ffb83
Show file tree
Hide file tree
Showing 18 changed files with 1,030 additions and 51 deletions.
18 changes: 18 additions & 0 deletions src/jelu-ui/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,15 @@ watch(() => route.name, (newVal, oldVal) => {
{{ t('nav.add_book') }}
</router-link>
</li>
<li>
<router-link
v-if="isLogged"
:to="{ name: 'history' }"
class="font-sans text-base capitalize"
>
{{ t('nav.history') }}
</router-link>
</li>
<li>
<router-link
v-if="isLogged"
Expand Down Expand Up @@ -253,6 +262,15 @@ watch(() => route.name, (newVal, oldVal) => {
{{ t('nav.add_book') }}
</router-link>
</li>
<li>
<router-link
v-if="isLogged"
:to="{ name: 'history' }"
class="font-sans text-xl capitalize"
>
{{ t('nav.history') }}
</router-link>
</li>
</ul>
<div
v-if="isLogged && showSearchInput"
Expand Down
206 changes: 206 additions & 0 deletions src/jelu-ui/src/components/History.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,206 @@
<script setup lang="ts">
import { useThrottleFn, useTitle } from '@vueuse/core';
import dayjs from "dayjs";
import { computed, Ref, ref, watch } from "vue";
import { useI18n } from 'vue-i18n';
import usePagination from '../composables/pagination';
import { ReadingEventType, ReadingEventWithUserBook } from '../model/ReadingEvent';
import dataService from "../services/DataService";
import BookCard from "./BookCard.vue";
import localizedFormat from 'dayjs/plugin/localizedFormat'
const { t, d } = useI18n({
inheritLocale: true,
useScope: 'global'
})
useTitle('Jelu | History')
dayjs.extend(localizedFormat)
const { total, page, pageAsNumber, perPage, updatePage, getPageIsLoading, updatePageLoading } = usePagination()
const nonCurrentlyReadingEvents: Array<ReadingEventType> = [ReadingEventType.DROPPED, ReadingEventType.FINISHED]
const yearEvents: Ref<Array<ReadingEventWithUserBook>> = ref([])
const getYears = () => {
dataService.yearsWithStats()
.then(res => {
years.value = res
})
.catch(e => {
console.log(e)
})
}
const eventsForYear = () => {
if (currentYear.value !== null) {
updatePageLoading(true)
dataService.myReadingEvents(nonCurrentlyReadingEvents, undefined, `${currentYear.value}-01-01`, `${currentYear.value + 1}-01-01`, pageAsNumber.value - 1, perPage.value)
.then(res => {
total.value = res.totalElements
yearEvents.value = res.content
if (! res.empty) {
page.value = (res.number + 1).toString(10)
}
else {
page.value = "1"
}
loading.value = false
updatePageLoading(false)
})
.catch(e => {
console.log(e)
loading.value = false
updatePageLoading(false)
})
}
}
const loading = ref(false)
const years: Ref<Array<number>> = ref([])
const currentYear: Ref<number|null> = ref(null)
watch(currentYear, (newVal, oldVal) => {
console.log("year " + newVal + " " + oldVal)
page.value = "1"
eventsForYear()
})
const loaderFullPage = ref(false)
// watches set above sometimes called twice
// so getBooks was sometimes called twice at the same instant
const throttledGetEvents = useThrottleFn(() => {
eventsForYear()
}, 100, false)
watch(page, (newVal, oldVal) => {
console.log("page " + newVal + " " + oldVal)
if (newVal !== oldVal) {
throttledGetEvents()
}
})
const eventsByMonth: Ref<Map<number, Array<ReadingEventWithUserBook>>> = computed(() => {
const monthEvents = new Map();
yearEvents.value.forEach(ev => {
let month = ev.modificationDate?.getMonth()
if (month !== undefined) {
month ++
}
if (!monthEvents.has(month)) {
monthEvents.set(month, [ev])
} else {
const existing: Array<ReadingEventWithUserBook> = monthEvents.get(month)
existing.push(ev)
monthEvents.set(month, existing)
}
})
console.log(monthEvents)
return monthEvents
})
getYears()
</script>

<template>
<div class="grid grid-cols-1 justify-center justify-items-center justify-self-center mb-3">
<h1
class="text-2xl typewriter w-11/12 sm:w-8/12 py-4 capitalize"
>
{{ t('history.years') }}
</h1>
<div
v-if="years != null && years !== undefined && years.length > 0"
class=""
>
<select
v-model="currentYear"
class="select select-bordered select-accent pt-2 mb-4"
>
<option
disabled
selected
>
{{ t('stats.choose_year') }}
</option>
<option
v-for="year in years"
:key="year"
:value="year"
>
{{ year }}
</option>
</select>
<div
v-for="[month, ev] in eventsByMonth"
:key="month"
>
<div class="flex items-center mx-2">
<svg
xmlns="http://www.w3.org/2000/svg"
class="h-6 w-6 inline"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path
stroke-linecap="round"
stroke-linejoin="round"
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg><h2 class="typewriter text-2xl text-left mx-2 my-2">
{{ dayjs(`2020-${month}-1`).format('MMMM') }}
</h2>
</div>
<div class="grid grid-cols-2 sm:grid-cols-8 gap-2 justify-center justify-items-center justify-self-center">
<div
v-for="event in ev"
:key="event.id"
>
<router-link
v-if="event.userBook.id != undefined"
:to="{ name: 'book-detail', params: { bookId: event.userBook.id } }"
>
<div class="relative h-full">
<book-card
:book="event.userBook"
class="h-full"
/>
<div class="badge badge-accent absolute bottom-0 left-1 ">
{{ d(event.modificationDate!!, 'short') }}
</div>
</div>
</router-link>
</div>
</div>
<div class="divider" />
</div>
</div>
</div>
<o-pagination
v-if="yearEvents.length > 0"
:current="pageAsNumber"
:total="total"
order="centered"
:per-page="perPage"
@change="updatePage"
/>
<o-loading
v-model:active="getPageIsLoading"
:full-page="true"
:can-cancel="true"
:overlay="loaderFullPage"
/>
</template>

<style scoped>
</style>
2 changes: 0 additions & 2 deletions src/jelu-ui/src/components/UserStats.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ const { t } = useI18n({
})
useTitle('Jelu | Stats')
console.log(dayjs('2020-1-1').format('MMMM'))
console.log(dayjs('2020-3-1').format('MMMM'))
ChartJS.register(Title, Tooltip, Legend, BarElement, CategoryScale, LinearScale)
Expand Down
4 changes: 2 additions & 2 deletions src/jelu-ui/src/components/Welcome.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ const nonCurrentlyReadingEvents: Array<ReadingEventType> = [ReadingEventType.DRO
const getMyEvents = async () => {
recentEventsIsLoading.value = true
try {
const res = await dataService.myReadingEvents(nonCurrentlyReadingEvents, 0, 8)
const res = await dataService.myReadingEvents(nonCurrentlyReadingEvents, undefined, undefined, undefined, 0, 8)
const notCurrentlyReading = res.content.filter(e => e.eventType !== ReadingEventType.CURRENTLY_READING)
events.value = notCurrentlyReading
recentEventsIsLoading.value = false
Expand Down Expand Up @@ -174,7 +174,7 @@ function toggleReadingEventModal(currentEvent: ReadingEvent, edit: boolean) {
<template #icon>
<span
v-tooltip="t('labels.mark_read_or_drop')"
class="icon has-text-info text-info"
class="icon text-info"
@click.prevent="toggleReadingEventModal(defaultCreateEvent(book.book.id!!), false)"
>
<i class="mdi mdi-check-circle mdi-18px" />
Expand Down
Loading

0 comments on commit e8ffb83

Please sign in to comment.