+
+ {isLoading ? (
+
+
+
+ ) : users.length === 0 ? (
+
{t('general.noResult')}
+ ) : isTableMode ? (
+
+
+
+
+ | UID |
+ {t('general.user.email')} |
+ {t('general.user.nickname')} |
+ {t('general.user.score')} |
+ {t('admin.permission')} |
+ {t('admin.verification')} |
+ {t('general.user.register-at')} |
+ {t('admin.operationsTitle')} |
+
+
+
+ {users.map((user, i) => (
+ handleEmailChange(user, i)}
+ onNicknameChange={() => handleNicknameChange(user, i)}
+ onScoreChange={() => handleScoreChange(user, i)}
+ onPermissionChange={() => handlePermissionChange(user, i)}
+ onVerificationToggle={() => handleVerificationToggle(user, i)}
+ onPasswordChange={() => handlePasswordChange(user)}
+ onDelete={() => handleDelete(user)}
+ />
+ ))}
+
+
+
+ ) : (
+
+ {users.map((user, i) => (
+ handleEmailChange(user, i)}
+ onNicknameChange={() => handleNicknameChange(user, i)}
+ onScoreChange={() => handleScoreChange(user, i)}
+ onPermissionChange={() => handlePermissionChange(user, i)}
+ onVerificationToggle={() => handleVerificationToggle(user, i)}
+ onPasswordChange={() => handlePasswordChange(user)}
+ onDelete={() => handleDelete(user)}
+ />
+ ))}
+
+ )}
+
+
+ )
+}
+
+export default hot(UsersManagement)
diff --git a/resources/assets/src/views/admin/UsersManagement/utils.ts b/resources/assets/src/views/admin/UsersManagement/utils.ts
new file mode 100644
index 00000000..3ef0b83f
--- /dev/null
+++ b/resources/assets/src/views/admin/UsersManagement/utils.ts
@@ -0,0 +1,27 @@
+import { t } from '@/scripts/i18n'
+import { User, UserPermission } from '@/scripts/types'
+
+export function humanizePermission(permission: UserPermission): string {
+ switch (permission) {
+ case UserPermission.Banned:
+ return t('admin.banned')
+ case UserPermission.Normal:
+ return t('admin.normal')
+ case UserPermission.Admin:
+ return t('admin.admin')
+ case UserPermission.SuperAdmin:
+ return t('admin.superAdmin')
+ }
+}
+
+export function verificationStatusText(isVerified: boolean): string {
+ return isVerified ? t('admin.verified') : t('admin.unverified')
+}
+
+export function canModifyUser(target: User, current: User): boolean {
+ return target.uid === current.uid || current.permission > target.permission
+}
+
+export function canModifyPermission(target: User, current: User): boolean {
+ return current.permission > target.permission
+}
diff --git a/resources/assets/tests/components/Modal.test.ts b/resources/assets/tests/components/Modal.test.ts
deleted file mode 100644
index 4a80291b..00000000
--- a/resources/assets/tests/components/Modal.test.ts
+++ /dev/null
@@ -1,216 +0,0 @@
-import $ from 'jquery'
-import 'bootstrap'
-import { mount } from '@vue/test-utils'
-import Modal from '@/components/Modal.vue'
-
-test('id', () => {
- const wrapper = mount(Modal, {
- propsData: {
- id: 'id',
- },
- })
- expect(wrapper.find('#id').exists()).toBeTrue()
-})
-
-test('title', () => {
- const wrapper = mount(Modal, {
- propsData: {
- title: 'kumiko',
- },
- })
- expect(wrapper.find('.modal-title').text()).toBe('kumiko')
-})
-
-test('close button at header', () => {
- const wrapper = mount(Modal)
- wrapper.find('.modal-header > button').trigger('click')
- expect(wrapper.emitted().dismiss).toHaveLength(1)
-})
-
-test('render lines', () => {
- const wrapper = mount(Modal, {
- propsData: {
- text: 'kumiko\nreina',
- },
- })
- const paragraphs = wrapper.findAll('p')
- expect(paragraphs).toHaveLength(2)
- expect(paragraphs.at(0).text()).toBe('kumiko')
- expect(paragraphs.at(1).text()).toBe('reina')
-})
-
-test('dynamic html', () => {
- const wrapper = mount(Modal, {
- propsData: {
- dangerousHTML: '