Client - get workouts ordered by distance, duration or average speed

This commit is contained in:
Sam 2021-11-02 15:12:57 +01:00
parent 05b22e6f72
commit e8350abf55
7 changed files with 90 additions and 26 deletions

View File

@ -9,7 +9,7 @@
@change="onSelectUpdate"
>
<option v-for="order in order_by" :value="order" :key="order">
{{ $t(`${message}.${order}`) }}
{{ $t(`${message}.${order.toUpperCase()}`) }}
</option>
</select>
</label>

View File

@ -157,9 +157,9 @@
</template>
<script lang="ts">
import { computed, ComputedRef, defineComponent, PropType } from 'vue'
import { computed, ComputedRef, defineComponent, PropType, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRouter } from 'vue-router'
import { LocationQuery, useRoute, useRouter } from 'vue-router'
import { ISport } from '@/types/sports'
import { IUserProfile } from '@/types/user'
@ -180,12 +180,13 @@
emits: ['filter'],
setup(props, { emit }) {
const { t } = useI18n()
const route = useRoute()
const router = useRouter()
const translatedSports: ComputedRef<ISport[]> = computed(() =>
translateSports(props.sports, t)
)
const params: Record<string, string> = {}
let params: LocationQuery = Object.assign({}, route.query)
function handleFilterChange(event: Event & { target: HTMLInputElement }) {
if (event.target.value === '') {
@ -199,6 +200,13 @@
router.push({ path: '/workouts', query: params })
}
watch(
() => route.query,
(newQuery) => {
params = Object.assign({}, newQuery)
}
)
return { translatedSports, onFilter, handleFilterChange }
},
})

View File

@ -1,6 +1,13 @@
<template>
<div class="workouts-list">
<div class="box" :class="{ 'empty-table': workouts.length === 0 }">
<FilterSelects
:sort="sortList"
:order_by="orderByList"
:query="query"
message="workouts"
@updateSelect="reloadWorkouts"
/>
<div class="workouts-table responsive-table">
<table>
<thead>
@ -103,26 +110,28 @@
PropType,
computed,
defineComponent,
ref,
watch,
capitalize,
onBeforeMount,
} from 'vue'
import { LocationQuery, useRoute } from 'vue-router'
import { LocationQuery, useRoute, useRouter } from 'vue-router'
import FilterSelects from '@/components/Common/FilterSelects.vue'
import StaticMap from '@/components/Common/StaticMap.vue'
import NoWorkouts from '@/components/Workouts/NoWorkouts.vue'
import { WORKOUTS_STORE } from '@/store/constants'
import { ITranslatedSport } from '@/types/sports'
import { IUserProfile } from '@/types/user'
import { IWorkout } from '@/types/workouts'
import { IWorkout, TWorkoutsPayload } from '@/types/workouts'
import { useStore } from '@/use/useStore'
import { getQuery, sortList, workoutsPayloadKeys } from '@/utils/api'
import { getDateWithTZ } from '@/utils/dates'
import { defaultOrder } from '@/utils/workouts'
export default defineComponent({
name: 'WorkoutsList',
components: {
FilterSelects,
NoWorkouts,
StaticMap,
},
@ -138,39 +147,70 @@
setup() {
const store = useStore()
const route = useRoute()
const router = useRouter()
const orderByList: string[] = [
'ave_speed',
'distance',
'duration',
'workout_date',
]
const workouts: ComputedRef<IWorkout[]> = computed(
() => store.getters[WORKOUTS_STORE.GETTERS.USER_WORKOUTS]
)
const per_page = 10
const page = ref(1)
let query: TWorkoutsPayload = getWorkoutsQuery(route.query)
onBeforeMount(() => {
loadWorkouts(route.query)
loadWorkouts(query)
})
function loadWorkouts(newQuery: LocationQuery) {
page.value = 1
store.dispatch(WORKOUTS_STORE.ACTIONS.GET_USER_WORKOUTS, {
page: page.value,
per_page,
...defaultOrder,
...newQuery,
function loadWorkouts(payload: TWorkoutsPayload) {
store.dispatch(WORKOUTS_STORE.ACTIONS.GET_USER_WORKOUTS, payload)
}
function reloadWorkouts(queryParam: string, queryValue: string) {
const newQuery: LocationQuery = Object.assign({}, route.query)
newQuery[queryParam] = queryValue
if (queryParam === 'per_page') {
newQuery['page'] = '1'
}
query = getWorkoutsQuery(newQuery)
router.push({ path: '/workouts', query })
}
function getWorkoutsQuery(newQuery: LocationQuery): TWorkoutsPayload {
query = getQuery(newQuery, orderByList, defaultOrder.order_by, {
defaultSort: defaultOrder.order,
query,
})
Object.keys(newQuery)
.filter((k) => workoutsPayloadKeys.includes(k))
.map((k) => {
if (typeof newQuery[k] === 'string') {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
query[k] = newQuery[k]
}
})
return query
}
watch(
() => route.query,
async (newQuery) => {
loadWorkouts(newQuery)
query = getWorkoutsQuery(newQuery)
loadWorkouts(query)
}
)
return {
query,
orderByList,
sortList,
workouts,
capitalize,
format,
getDateWithTZ,
reloadWorkouts,
}
},
})

View File

@ -36,10 +36,10 @@
},
"SELECTS": {
"ORDER_BY": {
"admin": "admin status",
"created_at": "registration date",
"username": "username",
"workouts_count": "workout count"
"ADMIN": "admin status",
"CREATED_AT": "registration date",
"USERNAME": "username",
"WORKOUTS_COUNT": "workout count"
}
}
}

View File

@ -36,10 +36,10 @@
},
"SELECTS": {
"ORDER_BY": {
"admin": "status administrateur",
"created_at": "date d'inscription",
"username": "nom d'utilisateur",
"workouts_count": "nombre de séances"
"ADMIN": "status administrateur",
"CREATED_AT": "date d'inscription",
"USERNAME": "nom d'utilisateur",
"WORKOUTS_COUNT": "nombre de séances"
}
}
}

View File

@ -1,3 +1,5 @@
import { TWorkoutsPayload } from '@/types/workouts'
export interface IPagination {
has_next: boolean
has_prev: boolean

View File

@ -48,3 +48,17 @@ export const getQuery = (
return query
}
export const workoutsPayloadKeys = [
'from',
'to',
'ave_speed_from',
'ave_speed_to',
'max_speed_from',
'max_speed_to',
'distance_from',
'distance_to',
'duration_from',
'duration_to',
'sport_id',
]