266 lines
7.6 KiB
JavaScript
266 lines
7.6 KiB
JavaScript
import { computed } from 'vue'
|
|
|
|
export function useAdminUsers({
|
|
api,
|
|
auth,
|
|
users,
|
|
userQuery,
|
|
userSort,
|
|
userSortDirection,
|
|
userAvatarInputs,
|
|
modalTargetUser,
|
|
modalPasswordDraft,
|
|
modalRoleNextAdmin,
|
|
modalUserDraftEmail,
|
|
modalUserDraftNickname,
|
|
modalUserDraftIsAdmin,
|
|
userEditModalOpen,
|
|
userPasswordModalOpen,
|
|
userDeleteModalOpen,
|
|
userRoleModalOpen,
|
|
resetMessages,
|
|
refreshUsers,
|
|
success,
|
|
error,
|
|
}) {
|
|
function setUserAvatarInput(userId, el) {
|
|
if (!userId) return
|
|
if (!el) {
|
|
delete userAvatarInputs.value[userId]
|
|
return
|
|
}
|
|
userAvatarInputs.value[userId] = el
|
|
}
|
|
|
|
const canManageModalRole = computed(() => {
|
|
if (!auth.user?.isPrimaryAdmin) return false
|
|
if (!modalTargetUser.value) return false
|
|
return !modalTargetUser.value.isPrimaryAdmin
|
|
})
|
|
|
|
const isUserEditDirty = computed(() => {
|
|
if (!modalTargetUser.value) return false
|
|
return (
|
|
modalUserDraftEmail.value.trim() !== (modalTargetUser.value.email || '') ||
|
|
modalUserDraftNickname.value.trim() !== (modalTargetUser.value.nickname || '') ||
|
|
!!modalUserDraftIsAdmin.value !== !!modalTargetUser.value.isAdmin
|
|
)
|
|
})
|
|
|
|
function roleLabelOf(user) {
|
|
if (user?.isPrimaryAdmin) return '최고 관리자'
|
|
if (user?.isAdmin) return '운영자'
|
|
return '일반 회원'
|
|
}
|
|
|
|
function openUserAvatarPicker(user) {
|
|
userAvatarInputs.value[user?.id]?.click()
|
|
}
|
|
|
|
async function uploadUserAvatar(user, file, { remove = false } = {}) {
|
|
resetMessages()
|
|
if (!user?.id) return
|
|
|
|
try {
|
|
user.isAvatarBusy = true
|
|
const data = await api.updateAdminUserAvatar(user.id, { file, removeAvatar: remove })
|
|
const updated = data.user
|
|
users.value = users.value.map((entry) =>
|
|
entry.id === updated.id
|
|
? {
|
|
...entry,
|
|
...updated,
|
|
isAvatarBusy: false,
|
|
}
|
|
: entry
|
|
)
|
|
if (modalTargetUser.value?.id === updated.id) {
|
|
modalTargetUser.value = { ...modalTargetUser.value, ...updated }
|
|
}
|
|
if (updated.id === auth.user?.id) await auth.refresh()
|
|
await refreshUsers()
|
|
success.value = remove ? '회원 썸네일을 삭제했어요.' : '회원 썸네일을 업데이트했어요.'
|
|
} catch (e) {
|
|
error.value = remove ? '회원 썸네일 삭제에 실패했어요.' : '회원 썸네일 변경에 실패했어요.'
|
|
} finally {
|
|
const target = users.value.find((entry) => entry.id === user.id)
|
|
if (target) target.isAvatarBusy = false
|
|
}
|
|
}
|
|
|
|
async function onUserAvatarChange(user, event) {
|
|
const file = event.target.files && event.target.files[0] ? event.target.files[0] : null
|
|
event.target.value = ''
|
|
if (!file) return
|
|
await uploadUserAvatar(user, file)
|
|
}
|
|
|
|
async function removeUserAvatar(user) {
|
|
if (!user?.avatarSrc) return
|
|
await uploadUserAvatar(user, null, { remove: true })
|
|
}
|
|
|
|
function openUserEditModal(user) {
|
|
resetMessages()
|
|
modalTargetUser.value = user ? { ...user } : null
|
|
modalUserDraftEmail.value = user?.email || ''
|
|
modalUserDraftNickname.value = user?.nickname || ''
|
|
modalUserDraftIsAdmin.value = !!user?.isAdmin
|
|
userEditModalOpen.value = true
|
|
}
|
|
|
|
function closeUserEditModal() {
|
|
userEditModalOpen.value = false
|
|
modalTargetUser.value = null
|
|
modalUserDraftEmail.value = ''
|
|
modalUserDraftNickname.value = ''
|
|
modalUserDraftIsAdmin.value = false
|
|
}
|
|
|
|
async function saveUserEdit() {
|
|
resetMessages()
|
|
if (!modalTargetUser.value?.id) return
|
|
|
|
try {
|
|
const data = await api.updateAdminUser(modalTargetUser.value.id, {
|
|
email: modalUserDraftEmail.value.trim(),
|
|
nickname: modalUserDraftNickname.value.trim(),
|
|
isAdmin: !!modalUserDraftIsAdmin.value,
|
|
})
|
|
const updated = data.user
|
|
users.value = users.value.map((entry) =>
|
|
entry.id === updated.id
|
|
? {
|
|
...entry,
|
|
...updated,
|
|
isAvatarBusy: entry.isAvatarBusy || false,
|
|
}
|
|
: entry
|
|
)
|
|
if (updated.id === auth.user?.id) await auth.refresh()
|
|
closeUserEditModal()
|
|
await refreshUsers()
|
|
success.value = '회원 정보를 저장했어요.'
|
|
} catch (e) {
|
|
error.value = '회원 정보 저장에 실패했어요.'
|
|
}
|
|
}
|
|
|
|
function openUserPasswordModal(user) {
|
|
resetMessages()
|
|
modalTargetUser.value = user ? { ...user } : null
|
|
modalPasswordDraft.value = ''
|
|
userPasswordModalOpen.value = true
|
|
}
|
|
|
|
function closeUserPasswordModal() {
|
|
userPasswordModalOpen.value = false
|
|
modalTargetUser.value = null
|
|
modalPasswordDraft.value = ''
|
|
}
|
|
|
|
function userDisplayName(user) {
|
|
return user?.nickname || user?.email?.split('@')[0] || '알 수 없음'
|
|
}
|
|
|
|
async function confirmUserPasswordReset() {
|
|
resetMessages()
|
|
if (!modalTargetUser.value?.id) return
|
|
|
|
const password = modalPasswordDraft.value.trim()
|
|
if (!password) {
|
|
error.value = '초기화할 비밀번호를 입력해주세요.'
|
|
return
|
|
}
|
|
|
|
try {
|
|
await api.updateAdminUserPassword(modalTargetUser.value.id, { password })
|
|
success.value = `${userDisplayName(modalTargetUser.value)} 계정 비밀번호를 초기화했어요.`
|
|
closeUserPasswordModal()
|
|
} catch (e) {
|
|
error.value = '비밀번호 초기화에 실패했어요.'
|
|
}
|
|
}
|
|
|
|
function openUserDeleteModal(user) {
|
|
resetMessages()
|
|
modalTargetUser.value = user ? { ...user } : null
|
|
userDeleteModalOpen.value = true
|
|
}
|
|
|
|
function closeUserDeleteModal() {
|
|
userDeleteModalOpen.value = false
|
|
modalTargetUser.value = null
|
|
}
|
|
|
|
async function confirmUserDelete() {
|
|
resetMessages()
|
|
if (!modalTargetUser.value?.id) return
|
|
|
|
try {
|
|
const deletingSelf = modalTargetUser.value.id === auth.user?.id
|
|
const deletedName = userDisplayName(modalTargetUser.value)
|
|
await api.deleteAdminUser(modalTargetUser.value.id)
|
|
users.value = users.value.filter((entry) => entry.id !== modalTargetUser.value.id)
|
|
closeUserDeleteModal()
|
|
success.value = `${deletedName} 계정을 삭제했어요.`
|
|
if (deletingSelf) await auth.refresh()
|
|
} catch (e) {
|
|
error.value = '회원 삭제에 실패했어요.'
|
|
}
|
|
}
|
|
|
|
function openUserRoleModal(user, nextIsAdmin = !modalUserDraftIsAdmin.value) {
|
|
resetMessages()
|
|
modalTargetUser.value = user ? { ...user } : null
|
|
modalRoleNextAdmin.value = !!nextIsAdmin
|
|
userRoleModalOpen.value = true
|
|
}
|
|
|
|
function closeUserRoleModal() {
|
|
userRoleModalOpen.value = false
|
|
if (!userEditModalOpen.value) modalTargetUser.value = null
|
|
modalRoleNextAdmin.value = false
|
|
}
|
|
|
|
function confirmUserRoleDraft() {
|
|
if (!modalTargetUser.value?.id) return
|
|
modalUserDraftIsAdmin.value = modalRoleNextAdmin.value
|
|
const targetLabel = modalRoleNextAdmin.value ? '운영자 권한을 저장 대기 상태로 반영했어요.' : '운영자 권한 해제를 저장 대기 상태로 반영했어요.'
|
|
closeUserRoleModal()
|
|
success.value = targetLabel
|
|
}
|
|
|
|
function submitUserFilters() {
|
|
refreshUsers({
|
|
q: userQuery.value,
|
|
sort: userSort.value,
|
|
direction: userSortDirection.value,
|
|
})
|
|
}
|
|
|
|
return {
|
|
setUserAvatarInput,
|
|
canManageModalRole,
|
|
isUserEditDirty,
|
|
roleLabelOf,
|
|
openUserAvatarPicker,
|
|
onUserAvatarChange,
|
|
removeUserAvatar,
|
|
openUserEditModal,
|
|
closeUserEditModal,
|
|
saveUserEdit,
|
|
openUserPasswordModal,
|
|
closeUserPasswordModal,
|
|
confirmUserPasswordReset,
|
|
openUserDeleteModal,
|
|
closeUserDeleteModal,
|
|
confirmUserDelete,
|
|
openUserRoleModal,
|
|
closeUserRoleModal,
|
|
confirmUserRoleDraft,
|
|
submitUserFilters,
|
|
userDisplayName,
|
|
}
|
|
}
|