Created
July 23, 2021 10:46
-
-
Save yoovanr/a545b022b15a00aac4da665cd90e7584 to your computer and use it in GitHub Desktop.
[Vue] pages/settings/accounts/index.vue
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="accounts-staff"> | |
<!-- top start --> | |
<div class="accounts-staff__top bottom-24"> | |
<AppTitle | |
class="mb-0" | |
bold="Accounts & permissions" | |
/> | |
<AppButton | |
size="small" | |
@click.native="$router.push({ name: 'settings-accounts-add' })" | |
> | |
Add account | |
</AppButton> | |
</div> | |
<!-- top end --> | |
<!-- lower start --> | |
<div class="accounts-staff__lower"> | |
<!-- table start --> | |
<div class="vtable-wrapper"> | |
<v-card> | |
<v-card-title> | |
<v-text-field | |
@input="updateAccountUsersSearch" | |
append-icon="mdi-magnify" | |
label="Search by name, e-mail, staff-id…" | |
single-line | |
hide-details | |
v-model="searchManagerValue" | |
></v-text-field> | |
</v-card-title> | |
<client-only> | |
<v-data-table | |
v-if="accountUsersData && accountUsersData.headers" | |
:headers="accountUsersData.headers" | |
:items="accountUsersData.content" | |
:search="search" | |
hide-default-footer | |
disable-pagination | |
> | |
<template v-slot:item="row"> | |
<tr> | |
<td> | |
<input | |
type="text" | |
:class="row.item.editable ? 'editable' : ''" | |
v-model="row.item.firstName" | |
:readonly="!row.item.editable" | |
/> | |
</td> | |
<td> | |
<input | |
type="text" | |
:class="row.item.editable ? 'editable' : ''" | |
v-model="row.item.lastName" | |
:readonly="!row.item.editable" | |
/> | |
</td> | |
<td class="id-cell"> | |
<input | |
type="text" | |
:class="row.item.editable ? 'editable' : ''" | |
v-model="row.item.staffId" | |
:readonly="!row.item.editable" | |
/> | |
</td> | |
<td class="email-cell"> | |
<input | |
type="email" | |
:class="row.item.editable ? 'editable' : ''" | |
v-model="row.item.email" | |
:readonly="!row.item.editable" | |
/> | |
</td> | |
<td> | |
<input | |
type="tel" | |
:class="row.item.editable ? 'editable' : ''" | |
v-model="row.item.phone" | |
:readonly="!row.item.editable" | |
/> | |
</td> | |
<td> | |
<select | |
:class="row.item.editable ? 'editable' : ''" | |
:readonly="!row.item.editable" | |
v-model="row.item.role" | |
> | |
<option :value="row.item.role" selected>{{ row.item.role }}</option> | |
<option value="Driver">Driver</option> | |
<option value="Filler">Filler</option> | |
<option value="Shopware">Shopware</option> | |
</select> | |
</td> | |
<td class="text-center"> | |
<CheckGreyIcon v-if="!row.item.status" /> | |
<CheckGreenIcon v-else/> | |
</td> | |
<td> | |
<!-- dropdown start --> | |
<button | |
class="dropdown__trigger" | |
@click="toggleClass($event, accountUsersData.content.indexOf(row.item))" | |
:ref="`dropdown-${accountUsersData.content.indexOf(row.item)}`" | |
> | |
<PointsIcon /> | |
</button> | |
<div | |
v-if="accountUsersData.content.indexOf(row.item) === selectedIndex" | |
class="dropdown" | |
v-click-outside="clickOutsideDropdown" | |
> | |
<div class="dropdown__inner"> | |
<button | |
@click="row.item.editable ? updateAccountUser(row.item) : row.item.editable = true; clickOutsideDropdown()" | |
> | |
<template v-if="row.item.editable">Save fields</template> | |
<template v-else>Edit fields</template> | |
</button> | |
<div> | |
<button | |
@click="row.item.showPassword = !row.item.showPassword" | |
> | |
Change password | |
</button> | |
<form | |
v-if="row.item.showPassword" | |
@submit.prevent="changeAccountUserPassword(row.item)" | |
class="dropdown-form" | |
> | |
<input | |
class="dropdown-form__input" | |
placeholder="Old password" | |
type="password" | |
v-model="row.item.oldPassword" | |
> | |
<input | |
class="dropdown-form__input" | |
placeholder="New password" | |
type="password" | |
v-model="row.item.newPassword" | |
> | |
<button class="dropdown-form__submit" type="submit">Change</button> | |
</form> | |
</div> | |
<button | |
@click="!row.item.status ? enableAccountUser(row.item) : disableAccountUser(row.item)" | |
> | |
<template v-if="!row.item.status">Activate user</template> | |
<template v-else>Deactivate user</template> | |
</button> | |
<button | |
@click="resendAccountUserVerification(row.item)" | |
> | |
Re-send verification Email | |
</button> | |
<button | |
@click="removeAccountUser(row.item)" | |
> | |
Delete account | |
</button> | |
</div> | |
</div> | |
<!-- dropdown end --> | |
</td> | |
</tr> | |
</template> | |
</v-data-table> | |
<v-pagination | |
v-if="Math.ceil(accountUsersTotalCount / accountUsersPerPage) > 1" | |
class="top-50" | |
v-model="accountUsersCurrentPage" | |
:length="Math.ceil(accountUsersTotalCount / accountUsersPerPage)" | |
:total-visible="7" | |
@input="updateAccountUsersCurrentPage" | |
></v-pagination> | |
</client-only> | |
</v-card> | |
</div> | |
<!-- table end --> | |
</div> | |
<!-- lower end --> | |
</div> | |
</template> | |
<script> | |
import { mapActions, mapGetters } from 'vuex' | |
import debounce from 'lodash.debounce' | |
import PointsIcon from '~/assets/images/points.svg' | |
import CheckGreyIcon from '~/assets/images/check_grey.svg' | |
import CheckGreenIcon from '~/assets/images/check_green.svg' | |
export default { | |
components: { | |
PointsIcon, | |
CheckGreyIcon, | |
CheckGreenIcon, | |
}, | |
data () { | |
return { | |
searchManagerValue: '', | |
selectedIndex: null, | |
} | |
}, | |
computed: { | |
...mapGetters('account-users', [ | |
'accountUsers', | |
'accountUsersLoading', | |
'accountUsersTotalCount', | |
'accountUsersCurrentPage', | |
'accountUsersPerPage', | |
'accountUsersSearch', | |
'enableAccountUserLoading', | |
'disableAccountUserLoading', | |
'resendAccountUserVerificationLoading', | |
]), | |
accountUsersData () { | |
const accountUsersData = { | |
headers: [ | |
{ text: 'Name', sortable: false, align: 'start', value: 'firstName' }, | |
{ text: 'Lastname', sortable: false, align: 'start', value: 'lastName' }, | |
{ text: 'Staff-ID', sortable: false, value: 'id' }, | |
{ text: 'E-Mail', sortable: false, value: 'email' }, | |
{ text: 'Phone', sortable: false, value: 'phone' }, | |
{ text: 'Job role', sortable: false, value: 'role' }, | |
{ text: 'Status', sortable: false, align: 'center', value: 'status' }, | |
{ text: '', sortable: false, value: 'settings' }, | |
], | |
content: [], | |
} | |
if (this.accountUsers && this.accountUsers.length) { | |
this.accountUsers.forEach((user) => { | |
const userData = { | |
firstName: user.firstName, | |
lastName: user.lastName, | |
staffId: user.staffId, | |
email: user.username, | |
phone: user.phoneNumber, | |
role: user.roles[0], | |
editable: false, | |
status: user.enabled, | |
settings: '', | |
id: user._id, | |
oldPassword: '', | |
newPassword: '', | |
showPassword: false, | |
} | |
accountUsersData.content.push(userData) | |
}) | |
} | |
return accountUsersData | |
}, | |
}, | |
async asyncData ({ store }) { | |
const params = { | |
page: store.state['account-users'].accountUsersCurrentPage, | |
perPage: store.state['account-users'].accountUsersPerPage, | |
search: store.state['account-users'].accountUsersSearch, | |
filter: 'Manager', | |
} | |
await store.dispatch('account-users/getAccountUsers', params) | |
if (store.state['account-users'].accountUsersSearch) { | |
return { | |
searchManagerValue: store.state['account-users'].accountUsersSearch, | |
} | |
} | |
}, | |
methods: { | |
...mapActions('account-users', { | |
getAccountUsersAction: 'getAccountUsers', | |
updateAccountUsersCurrentPageAction: 'updateAccountUsersCurrentPage', | |
updateAccountUsersFilterAction: 'updateAccountUsersFilter', | |
updateAccountUsersSearchAction: 'updateAccountUsersSearch', | |
updateAccountUserAction: 'updateAccountUser', | |
enableAccountUserAction: 'enableAccountUser', | |
disableAccountUserAction: 'disableAccountUser', | |
changeAccountUserPasswordAction: 'changeAccountUserPassword', | |
removeAccountUserAction: 'removeAccountUser', | |
resendAccountUserVerificationAction: 'resendAccountUserVerification', | |
}), | |
getAccountUsers () { | |
const params = { | |
page: this.accountUsersCurrentPage, | |
perPage: this.accountUsersPerPage, | |
search: this.accountUsersSearch, | |
filter: 'Manager', | |
} | |
this.getAccountUsersAction(params) | |
}, | |
updateAccountUsersCurrentPage(page){ | |
this.updateAccountUsersCurrentPageAction(page) | |
this.getAccountUsers() | |
}, | |
updateAccountUsersSearch(search) { | |
const that = this | |
debounce(() => { | |
that.updateAccountUsersCurrentPageAction(1) | |
that.updateAccountUsersSearchAction(search) | |
that.getAccountUsers() | |
}, 500)() | |
}, | |
async updateAccountUser(data) { | |
try { | |
await this.updateAccountUserAction(data) | |
this.$notify({ | |
type: 'success', | |
title: 'User successfully updated!', | |
}) | |
data.editable = false | |
this.updateAccountUsersCurrentPageAction(1) | |
this.getAccountUsers() | |
} catch (err) {} | |
}, | |
async removeAccountUser ({ id }) { | |
try { | |
await this.removeAccountUserAction({ id }) | |
this.$notify({ | |
type: 'success', | |
title: 'User successfully removed!', | |
}) | |
} catch (err) {} | |
this.clickOutsideDropdown() | |
}, | |
async enableAccountUser ({ id }) { | |
try { | |
await this.enableAccountUserAction({ id }) | |
this.$notify({ | |
type: 'success', | |
title: 'User successfully activated!', | |
}) | |
} catch (err) {} | |
this.clickOutsideDropdown() | |
}, | |
async disableAccountUser ({ id }) { | |
try { | |
await this.disableAccountUserAction({ id }) | |
this.$notify({ | |
type: 'success', | |
title: 'User successfully deactivated!', | |
}) | |
} catch (err) {} | |
this.clickOutsideDropdown() | |
}, | |
async changeAccountUserPassword (data) { | |
try { | |
await this.changeAccountUserPasswordAction(data) | |
this.$notify({ | |
type: 'success', | |
title: 'Password successfully changed!', | |
}) | |
data.oldPassword = '' | |
data.newPassword = '' | |
data.showPassword = false | |
} catch (err) {} | |
this.clickOutsideDropdown() | |
}, | |
async resendAccountUserVerification ({ id }) { | |
try { | |
await this.resendAccountUserVerificationAction({ id }) | |
this.$notify({ | |
type: 'success', | |
title: 'Resend user verification!', | |
}) | |
} catch (err) {} | |
this.clickOutsideDropdown() | |
}, | |
toggleClass(event, index) { | |
if (!this.$refs[`dropdown-${index}`].classList.contains('dropdown__trigger--active')) { | |
this.$refs[`dropdown-${index}`].classList.value = 'dropdown__trigger--active' | |
this.selectedIndex = index | |
} else { | |
this.$refs[`dropdown-${index}`].classList.value = 'dropdown__trigger' | |
this.selectedIndex = null | |
} | |
}, | |
clickOutsideDropdown() { | |
if (this.selectedIndex !== null) { | |
this.$refs[`dropdown-${this.selectedIndex}`].classList.value = 'dropdown__trigger' | |
this.selectedIndex = null | |
} | |
}, | |
}, | |
} | |
</script> | |
<style lang="scss" scoped> | |
.accounts-staff { | |
&__top { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
} | |
input, | |
select { | |
padding: 3px 0 0 0; | |
max-width: auto; | |
transition: color .3s; | |
border-bottom: 1px solid transparent; | |
} | |
td:last-of-type, | |
th:last-of-type { | |
padding: 8px 0; | |
} | |
input.editable, | |
select.editable { | |
color: #687584; | |
border-color:#ADB4C6; | |
transition: all .3s; | |
} | |
input.editable:focus { | |
border-color: #000; | |
} | |
} | |
</style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment