Client - add selects to sort users in administration

This commit is contained in:
Sam 2021-10-31 13:27:16 +01:00
parent 80afbe5968
commit 4a5f175053
9 changed files with 189 additions and 26 deletions

View File

@ -54,7 +54,7 @@
</td>
<td class="sport-action">
<span class="cell-heading">
{{ $t('admin.SPORTS.TABLE.ACTION') }}
{{ $t('admin.ACTION') }}
</span>
<div class="action-button">
<button

View File

@ -6,6 +6,12 @@
<button class="top-button" @click.prevent="$router.push('/admin')">
{{ $t('admin.BACK_TO_ADMIN') }}
</button>
<AdminUsersSelects
:sort="sort"
:order_by="order_by"
:query="query"
@updateSelect="reloadUsers"
/>
<div class="responsive-table">
<table>
<thead>
@ -101,35 +107,39 @@
ComputedRef,
computed,
defineComponent,
reactive,
watch,
capitalize,
onBeforeMount,
} from 'vue'
import { useRoute, LocationQuery } from 'vue-router'
import { LocationQuery, useRoute, useRouter } from 'vue-router'
import AdminUsersSelects from '@/components/Administration/AdminUsersSelects.vue'
import Pagination from '@/components/Common/Pagination.vue'
import { ROOT_STORE, USER_STORE, USERS_STORE } from '@/store/constants'
import { IPagination, IPaginationPayload } from '@/types/api'
import { IPagination, TPaginationPayload } from '@/types/api'
import { IUserProfile } from '@/types/user'
import { useStore } from '@/use/useStore'
export default defineComponent({
name: 'AdminUsers',
components: {
AdminUsersSelects,
Pagination,
},
setup() {
const store = useStore()
const route = useRoute()
const router = useRouter()
const orders: string[] = ['asc', 'desc']
const order_types: string[] = [
const sort: string[] = ['asc', 'desc']
const order_by: string[] = [
'admin',
'created_at',
'username',
'workouts_count',
]
let query: IPaginationPayload = getQuery(route.query)
let query: TPaginationPayload = reactive(getQuery(route.query))
const authUser: ComputedRef<IUserProfile> = computed(
() => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]
@ -144,7 +154,7 @@
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
)
function loadUsers(queryParams: IPaginationPayload) {
function loadUsers(queryParams: TPaginationPayload) {
store.dispatch(USERS_STORE.ACTIONS.GET_USERS, queryParams)
}
function getPage(page: string | (string | null)[] | null): number {
@ -156,18 +166,16 @@
: 10
}
function getOrder(order: string | (string | null)[] | null): string {
return order && typeof order === 'string' && orders.includes(order)
return order && typeof order === 'string' && sort.includes(order)
? order
: 'asc'
}
function getOrderBy(order_by: string | (string | null)[] | null): string {
return order_by &&
typeof order_by === 'string' &&
order_types.includes(order_by)
? order_by
function getOrderBy(order: string | (string | null)[] | null): string {
return order && typeof order === 'string' && order_by.includes(order)
? order
: 'created_at'
}
function getQuery(query: LocationQuery): IPaginationPayload {
function getQuery(query: LocationQuery): TPaginationPayload {
return {
page: getPage(query.page),
per_page: getPerPage(query.per_page),
@ -181,14 +189,24 @@
admin,
})
}
function reloadUsers(queryParam: string, queryValue: string) {
query[queryParam] = queryValue
if (queryParam === 'per_page') {
query.page = 1
}
router.push({ path: '/admin/users', query })
}
onBeforeMount(() => loadUsers(query))
watch(
() => route.query,
(newQuery) => {
query = getQuery(newQuery)
loadUsers(getQuery(newQuery))
(newQuery: LocationQuery) => {
query.page = getPage(newQuery.page)
query.per_page = getPerPage(newQuery.per_page)
query.order = getOrder(newQuery.order)
query.order_by = getOrderBy(newQuery.order_by)
loadUsers(query)
}
)
@ -196,9 +214,12 @@
authUser,
errorMessages,
pagination,
order_by,
query,
sort,
users,
capitalize,
reloadUsers,
updateUser,
}
},
@ -225,6 +246,9 @@
display: block;
margin-bottom: $default-margin * 2;
}
.pagination-center {
margin-top: -3 * $default-margin;
}
}
}
</style>

View File

@ -0,0 +1,105 @@
<template>
<div class="table-selects">
<label>
{{ $t('admin.USERS.SELECTS.ORDER_BY.LABEL') }}:
<select
name="order_by"
id="order_by"
:value="query.order_by"
@change="onSelectUpdate"
>
<option v-for="order in order_by" :value="order" :key="order">
{{ $t(`admin.USERS.SELECTS.ORDER_BY.${order}`) }}
</option>
</select>
</label>
<label>
{{ $t('admin.USERS.SELECTS.ORDER.LABEL') }}:
<select
name="order"
id="order"
:value="query.order"
@change="onSelectUpdate"
>
<option v-for="order in sort" :value="order" :key="order">
{{ $t(`admin.USERS.SELECTS.ORDER.${order.toUpperCase()}`) }}
</option>
</select>
</label>
<label>
{{ $t('admin.USERS.SELECTS.PER_PAGE.LABEL') }}:
<select
name="per_page"
id="per_page"
:value="query.per_page"
@change="onSelectUpdate"
>
<option v-for="nb in per_page" :value="nb" :key="nb">
{{ nb }}
</option>
</select>
</label>
</div>
</template>
<script lang="ts">
import { PropType, defineComponent } from 'vue'
import { TPaginationPayload } from '@/types/api'
export default defineComponent({
name: 'AdminUsersSelects',
props: {
order_by: {
type: Object as PropType<string[]>,
required: true,
},
query: {
type: Object as PropType<TPaginationPayload>,
required: true,
},
sort: {
type: Object as PropType<string[]>,
required: true,
},
},
emits: ['updateSelect'],
setup(props, { emit }) {
function onSelectUpdate(event: Event & { target: HTMLInputElement }) {
emit('updateSelect', event.target.id, event.target.value)
}
return {
per_page: [10, 50, 100],
onSelectUpdate,
}
},
})
</script>
<style lang="scss" scoped>
@import '~@/scss/base.scss';
.table-selects {
display: flex;
justify-content: space-between;
margin: $default-margin 0;
label {
select {
margin-left: $default-margin;
padding: $default-padding * 0.5;
}
}
@media screen and (max-width: $small-limit) {
flex-wrap: wrap;
label {
margin-bottom: $default-margin;
select {
margin-left: 0;
}
}
}
}
</style>

View File

@ -38,7 +38,7 @@
<script lang="ts">
import { PropType, defineComponent } from 'vue'
import { IPagination, IPaginationPayload } from '@/types/api'
import { IPagination, TPaginationPayload } from '@/types/api'
export default defineComponent({
name: 'Pagination',
@ -52,7 +52,7 @@
required: true,
},
query: {
type: Object as PropType<IPaginationPayload>,
type: Object as PropType<TPaginationPayload>,
required: true,
},
},
@ -60,7 +60,7 @@
function rangePagination(pages: number): number[] {
return Array.from({ length: pages }, (_, i) => i + 1)
}
function getQuery(page: number, cursor?: number): IPaginationPayload {
function getQuery(page: number, cursor?: number): TPaginationPayload {
const newQuery = Object.assign({}, props.query)
newQuery.page = cursor ? page + cursor : page
return newQuery

View File

@ -31,6 +31,23 @@
"TABLE": {
"ADD_ADMIN_RIGHTS": "Add admin rights",
"REMOVE_ADMIN_RIGHTS": "Remove admin rights"
},
"SELECTS": {
"ORDER_BY": {
"LABEL": "order by",
"admin": "admin status",
"created_at": "registration date",
"username": "username",
"workouts_count": "workout count"
},
"ORDER": {
"LABEL": "sort",
"ASC": "ascending",
"DESC": "descending"
},
"PER_PAGE": {
"LABEL": "par page"
}
}
}
}

View File

@ -31,6 +31,23 @@
"TABLE": {
"ADD_ADMIN_RIGHTS": "Ajouter les drois d'admin",
"REMOVE_ADMIN_RIGHTS": "Retirer les drois d'admin"
},
"SELECTS": {
"ORDER_BY": {
"LABEL": "trier par ",
"admin": "status administrateur",
"created_at": "date d'inscription",
"username": "nom d'utilisateur",
"workouts_count": "nombre de séances"
},
"ORDER": {
"LABEL": "tri",
"ASC": "ascendant",
"DESC": "descendant"
},
"PER_PAGE": {
"LABEL": "par page"
}
}
}
}

View File

@ -4,14 +4,14 @@ import authApi from '@/api/authApi'
import { ROOT_STORE, USERS_STORE } from '@/store/constants'
import { IRootState } from '@/store/modules/root/types'
import { IUsersActions, IUsersState } from '@/store/modules/users/types'
import { IPaginationPayload } from '@/types/api'
import { TPaginationPayload } from '@/types/api'
import { IAdminUserPayload } from '@/types/user'
import { handleError } from '@/utils'
export const actions: ActionTree<IUsersState, IRootState> & IUsersActions = {
[USERS_STORE.ACTIONS.GET_USERS](
context: ActionContext<IUsersState, IRootState>,
payload: IPaginationPayload
payload: TPaginationPayload
): void {
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
context.commit(USERS_STORE.MUTATIONS.UPDATE_USERS_LOADING, true)
@ -40,7 +40,6 @@ export const actions: ActionTree<IUsersState, IRootState> & IUsersActions = {
context: ActionContext<IUsersState, IRootState>,
payload: IAdminUserPayload
): void {
console.log('payload', payload)
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
authApi
.patch(`users/${payload.username}`, { admin: payload.admin })

View File

@ -7,7 +7,7 @@ import {
import { USERS_STORE } from '@/store/constants'
import { IRootState } from '@/store/modules/root/types'
import { IPagination, IPaginationPayload } from '@/types/api'
import { IPagination, TPaginationPayload } from '@/types/api'
import { IAdminUserPayload, IUserProfile } from '@/types/user'
export interface IUsersState {
@ -19,7 +19,7 @@ export interface IUsersState {
export interface IUsersActions {
[USERS_STORE.ACTIONS.GET_USERS](
context: ActionContext<IUsersState, IRootState>,
payload: IPaginationPayload
payload: TPaginationPayload
): void
[USERS_STORE.ACTIONS.UPDATE_USER](
context: ActionContext<IUsersState, IRootState>,

View File

@ -6,7 +6,8 @@ export interface IPagination {
total: number
}
export interface IPaginationPayload {
export type TPaginationPayload = {
[key: string]: string | number
order: string
order_by: string
per_page: number