Client - display pagination on workouts list
This commit is contained in:
@ -8,16 +8,22 @@
|
||||
:event="pagination.has_prev ? 'click' : ''"
|
||||
:disabled="!pagination.has_prev"
|
||||
>
|
||||
<i class="fa fa-chevron-left" aria-hidden="true" />
|
||||
{{ $t('api.PAGINATION.PREVIOUS') }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li
|
||||
v-for="page in rangePagination(pagination.pages)"
|
||||
v-for="page in rangePagination(pagination.pages, pagination.page)"
|
||||
:key="page"
|
||||
class="page"
|
||||
:class="{ active: page === pagination.page }"
|
||||
>
|
||||
<router-link class="page-link" :to="{ path, query: getQuery(page) }">
|
||||
<span v-if="page === '...'"> ... </span>
|
||||
<router-link
|
||||
v-else
|
||||
class="page-link"
|
||||
:to="{ path, query: getQuery(+page) }"
|
||||
>
|
||||
{{ page }}
|
||||
</router-link>
|
||||
</li>
|
||||
@ -29,6 +35,7 @@
|
||||
:disabled="!pagination.has_next"
|
||||
>
|
||||
{{ $t('api.PAGINATION.NEXT') }}
|
||||
<i class="fa fa-chevron-right" aria-hidden="true" />
|
||||
</router-link>
|
||||
</li>
|
||||
</ul>
|
||||
@ -39,6 +46,7 @@
|
||||
import { PropType, defineComponent } from 'vue'
|
||||
|
||||
import { IPagination, TPaginationPayload } from '@/types/api'
|
||||
import { rangePagination } from '@/utils/api'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'Pagination',
|
||||
@ -57,9 +65,6 @@
|
||||
},
|
||||
},
|
||||
setup(props) {
|
||||
function rangePagination(pages: number): number[] {
|
||||
return Array.from({ length: pages }, (_, i) => i + 1)
|
||||
}
|
||||
function getQuery(page: number, cursor?: number): TPaginationPayload {
|
||||
const newQuery = Object.assign({}, props.query)
|
||||
newQuery.page = cursor ? page + cursor : page
|
||||
@ -115,6 +120,18 @@
|
||||
border-bottom-right-radius: 5px;
|
||||
margin-left: -1px;
|
||||
}
|
||||
.fa {
|
||||
font-size: 0.8em;
|
||||
padding: 0 $default-padding * 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: $medium-limit) {
|
||||
.pagination {
|
||||
.page {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -143,7 +143,7 @@
|
||||
sum += tooltipItem.parsed.y
|
||||
})
|
||||
return (
|
||||
`${t('statistics.TOTAL')}: ` +
|
||||
`${t('common.TOTAL')}: ` +
|
||||
formatTooltipValue(props.displayedData, sum)
|
||||
)
|
||||
},
|
||||
|
@ -197,6 +197,9 @@
|
||||
}
|
||||
function onFilter() {
|
||||
emit('filter')
|
||||
if ('page' in params) {
|
||||
params['page'] = '1'
|
||||
}
|
||||
router.push({ path: '/workouts', query: params })
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,15 @@
|
||||
<template>
|
||||
<div class="workouts-list">
|
||||
<div class="box" :class="{ 'empty-table': workouts.length === 0 }">
|
||||
<div class="total">
|
||||
<span class="total-label">
|
||||
{{ $t('common.TOTAL').toLowerCase() }}:
|
||||
</span>
|
||||
<span v-if="pagination.total">
|
||||
{{ pagination.total }}
|
||||
{{ $t('workouts.WORKOUT', pagination.total) }}
|
||||
</span>
|
||||
</div>
|
||||
<FilterSelects
|
||||
:sort="sortList"
|
||||
:order_by="orderByList"
|
||||
@ -9,6 +18,12 @@
|
||||
@updateSelect="reloadWorkouts"
|
||||
/>
|
||||
<div class="workouts-table responsive-table">
|
||||
<Pagination
|
||||
class="top-pagination"
|
||||
:pagination="pagination"
|
||||
path="/workouts"
|
||||
:query="query"
|
||||
/>
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@ -96,6 +111,7 @@
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<Pagination :pagination="pagination" path="/workouts" :query="query" />
|
||||
</div>
|
||||
</div>
|
||||
<NoWorkouts v-if="workouts.length === 0" />
|
||||
@ -117,9 +133,11 @@
|
||||
import { LocationQuery, useRoute, useRouter } from 'vue-router'
|
||||
|
||||
import FilterSelects from '@/components/Common/FilterSelects.vue'
|
||||
import Pagination from '@/components/Common/Pagination.vue'
|
||||
import StaticMap from '@/components/Common/StaticMap.vue'
|
||||
import NoWorkouts from '@/components/Workouts/NoWorkouts.vue'
|
||||
import { WORKOUTS_STORE } from '@/store/constants'
|
||||
import { IPagination } from '@/types/api'
|
||||
import { ITranslatedSport } from '@/types/sports'
|
||||
import { IUserProfile } from '@/types/user'
|
||||
import { IWorkout, TWorkoutsPayload } from '@/types/workouts'
|
||||
@ -133,6 +151,7 @@
|
||||
components: {
|
||||
FilterSelects,
|
||||
NoWorkouts,
|
||||
Pagination,
|
||||
StaticMap,
|
||||
},
|
||||
props: {
|
||||
@ -158,6 +177,9 @@
|
||||
const workouts: ComputedRef<IWorkout[]> = computed(
|
||||
() => store.getters[WORKOUTS_STORE.GETTERS.USER_WORKOUTS]
|
||||
)
|
||||
const pagination: ComputedRef<IPagination> = computed(
|
||||
() => store.getters[WORKOUTS_STORE.GETTERS.WORKOUTS_PAGINATION]
|
||||
)
|
||||
let query: TWorkoutsPayload = getWorkoutsQuery(route.query)
|
||||
|
||||
onBeforeMount(() => {
|
||||
@ -205,6 +227,7 @@
|
||||
return {
|
||||
query,
|
||||
orderByList,
|
||||
pagination,
|
||||
sortList,
|
||||
workouts,
|
||||
capitalize,
|
||||
@ -225,11 +248,36 @@
|
||||
width: 100%;
|
||||
|
||||
.box {
|
||||
padding: $default-padding $default-padding * 2;
|
||||
@media screen and (max-width: $small-limit) {
|
||||
&.empty-table {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.total {
|
||||
display: flex;
|
||||
gap: $default-padding * 0.5;
|
||||
.total-label {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.top-pagination {
|
||||
display: none;
|
||||
|
||||
@media screen and (max-width: $small-limit) {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
::v-deep(.pagination-center) {
|
||||
@media screen and (max-width: $small-limit) {
|
||||
ul {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.workouts-table {
|
||||
.sport-col {
|
||||
padding-right: 0;
|
||||
|
Reference in New Issue
Block a user