- Complete GGZ Ecademy Nuxt.js user portal - Learning products browser and management - Member management interface - User authentication and roles - Multi-language support (NL/EN) - Vuex store for state management - Component-based architecture
This commit is contained in:
186
pages/manager/accounts/index.vue
Normal file
186
pages/manager/accounts/index.vue
Normal file
@@ -0,0 +1,186 @@
|
||||
<template>
|
||||
<div>
|
||||
<page-header v-if="users" class="d-flex justify-space-between">
|
||||
<span> {{ $t('auth.account.management') }} ({{ users.length }}) </span>
|
||||
<v-btn
|
||||
color="accent"
|
||||
depressed
|
||||
rounded
|
||||
:to="localePath('/manager/accounts/new')"
|
||||
v-if="$store.getters.isAdmin"
|
||||
>
|
||||
<v-icon left x-small>icon-add</v-icon>
|
||||
<small>{{ $t('general.add') }}</small>
|
||||
</v-btn>
|
||||
</page-header>
|
||||
|
||||
<v-data-table
|
||||
:headers="headers"
|
||||
:items="users"
|
||||
:items-per-page="5"
|
||||
class="pa-4 secondary"
|
||||
>
|
||||
<template v-slot:item.fullName="{ item }">
|
||||
<v-avatar size="40" class="primary has-outline">
|
||||
<img :src="item.image.thumb || noImage" :alt="item.fullName" />
|
||||
</v-avatar>
|
||||
<span class="ml-4">
|
||||
{{ item.fullName }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<template v-slot:item.roles="{ item }">
|
||||
<v-chip
|
||||
class="ma-2"
|
||||
v-for="role in item.roles"
|
||||
:color="role.color"
|
||||
:key="role.name"
|
||||
outlined
|
||||
>{{ role.name }}</v-chip
|
||||
>
|
||||
</template>
|
||||
|
||||
<template v-slot:item.actions="{ item }">
|
||||
<v-menu offset-y>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-btn v-on="on" fab small outlined color="info" x-small>
|
||||
<v-icon small>icon-options</v-icon>
|
||||
</v-btn>
|
||||
</template>
|
||||
<v-list>
|
||||
<v-list-item nuxt :to="localePath(`/manager/accounts/${item.id}`)">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-edit</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-title>{{ $t('general.edit') }}</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-dialog v-model="dialog" persistent max-width="500">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-list-item v-on="on">
|
||||
<v-list-item-icon class="mr-1">
|
||||
<v-icon small>icon-remove</v-icon>
|
||||
</v-list-item-icon>
|
||||
|
||||
<v-list-item-title>{{
|
||||
$t('general.delete')
|
||||
}}</v-list-item-title>
|
||||
</v-list-item>
|
||||
</template>
|
||||
<v-card class="primary" flat>
|
||||
<v-card-title class="headline">{{
|
||||
$t('user.delete.confirmation')
|
||||
}}</v-card-title>
|
||||
<v-card-text>{{ $t('user.delete.info') }}</v-card-text>
|
||||
<v-card-actions>
|
||||
<div class="ma-4">
|
||||
<v-btn
|
||||
color="accent"
|
||||
class="mx-2"
|
||||
@click="deleteUser(item.id)"
|
||||
rounded
|
||||
depressed
|
||||
>{{ $t('user.delete.yes') }}</v-btn
|
||||
>
|
||||
<v-btn
|
||||
class="mx-2"
|
||||
color="info"
|
||||
@click="close"
|
||||
rounded
|
||||
depressed
|
||||
>{{ $t('general.back') }}</v-btn
|
||||
>
|
||||
</div>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</template>
|
||||
</v-data-table>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import PageHeader from '~/components/UI/PageHeader/PageHeader'
|
||||
|
||||
export default {
|
||||
layout: `${process.env.CUSTOMER}Admin`,
|
||||
middleware: 'onlySuperAdmins',
|
||||
components: {
|
||||
PageHeader,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
dialog: false,
|
||||
users: [],
|
||||
headers: [
|
||||
{ text: this.$t('general.name'), sortable: true, value: 'fullName' },
|
||||
{ text: this.$t('general.email'), value: 'email', sortable: true },
|
||||
{ text: this.$t('general.roles'), value: 'roles' },
|
||||
{ text: this.$t('general.actions'), value: 'actions', sortable: false },
|
||||
],
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
noImage() {
|
||||
return require(`@/assets/img/no_image.png`)
|
||||
},
|
||||
},
|
||||
|
||||
watch: {
|
||||
dialog(val) {
|
||||
val || this.close()
|
||||
},
|
||||
},
|
||||
|
||||
async asyncData({ $axios }) {
|
||||
const response = await $axios.get('/admin/users')
|
||||
return { users: response.data }
|
||||
},
|
||||
|
||||
methods: {
|
||||
close() {
|
||||
this.dialog = false
|
||||
},
|
||||
|
||||
save() {
|
||||
this.close()
|
||||
},
|
||||
|
||||
async deleteUser(userId) {
|
||||
if (!userId) {
|
||||
this.$notifier.showMessage({
|
||||
content: `No User to delete selected`,
|
||||
color: 'error',
|
||||
icon: 'icon-message',
|
||||
})
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await this.$axios.delete(`/admin/users/${userId}`)
|
||||
this.users = this.users.filter((user) => user.id !== userId)
|
||||
this.dialog = false
|
||||
|
||||
this.$notifier.showMessage({
|
||||
content: `User deleted`,
|
||||
color: 'success',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
} catch (error) {
|
||||
this.$notifier.showMessage({
|
||||
content: `Error trying to delete the selected user`,
|
||||
color: 'error',
|
||||
icon: 'mdi-delete',
|
||||
})
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.has-outline {
|
||||
box-shadow: 0 0 0 3px #eef7f9;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user