135 lines
4.5 KiB
Vue
135 lines
4.5 KiB
Vue
<template>
|
|
<ul class="list-unstyled users-list d-flex align-items-center gap-1">
|
|
<li
|
|
v-for="(user, index) in sortedUserList"
|
|
:key="index"
|
|
class="avatar pull-up"
|
|
:class="{ 'opacity-100': isUserDisabled(user) }"
|
|
@click.stop="toggleDisable(index)"
|
|
data-bs-toggle="tooltip"
|
|
data-popup="tooltip-custom"
|
|
data-bs-placement="top"
|
|
:aria-label="user.MEMBERSEQ"
|
|
:data-bs-original-title="getTooltipTitle(user)"
|
|
>
|
|
<img
|
|
class="rounded-circle user-avatar border border-3"
|
|
:class="{ 'grayscaleImg': isUserDisabled(user) }"
|
|
:src="`${baseUrl}upload/img/profile/${user.MEMBERPRF}`"
|
|
:style="`border-color: ${user.usercolor} !important;`"
|
|
@error="$event.target.src = '/img/icons/icon.png'"
|
|
alt="user"
|
|
/>
|
|
</li>
|
|
</ul>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, ref, nextTick, computed } from 'vue';
|
|
import { useUserStore } from '@s/userList';
|
|
import $api from '@api';
|
|
|
|
const emit = defineEmits(['user-list-update']);
|
|
const userStore = useUserStore();
|
|
const userList = ref([]);
|
|
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, '');
|
|
|
|
const props = defineProps({
|
|
projctSeq: {
|
|
type: Number,
|
|
required: false,
|
|
}
|
|
});
|
|
|
|
// 활성화된 회원을 앞으로 정렬하는 computed 속성
|
|
const sortedUserList = computed(() => {
|
|
return [...userList.value].sort((a, b) => {
|
|
const aDisabled = isUserDisabled(a);
|
|
const bDisabled = isUserDisabled(b);
|
|
|
|
// 활성화된 사용자가 먼저 오도록 정렬
|
|
if (!aDisabled && bDisabled) return -1;
|
|
if (aDisabled && !bDisabled) return 1;
|
|
return 0;
|
|
});
|
|
});
|
|
|
|
// 사용자의 프로젝트 참여 상태 확인
|
|
const fetchProjectParticipation = async () => {
|
|
if (props.projctSeq) {
|
|
const response = await $api.get(`project/members/${props.projctSeq}`);
|
|
if (response.status === 200) {
|
|
const projectMembers = response.data.data;
|
|
userList.value = userList.value.map(user => ({
|
|
...user,
|
|
PROJCTYON: projectMembers.find(pm => pm.MEMBERSEQ === user.MEMBERSEQ)?.PROJCTYON ?? '1'
|
|
}));
|
|
}
|
|
}
|
|
};
|
|
|
|
// 사용자 목록 호출
|
|
onMounted(async () => {
|
|
await userStore.fetchUserList();
|
|
userList.value = userStore.userList;
|
|
|
|
if (props.projctSeq) {
|
|
await fetchProjectParticipation();
|
|
}
|
|
|
|
nextTick(() => {
|
|
const tooltips = document.querySelectorAll('[data-bs-toggle="tooltip"]');
|
|
tooltips.forEach((tooltip) => {
|
|
new bootstrap.Tooltip(tooltip);
|
|
});
|
|
});
|
|
});
|
|
|
|
// 사용자 비활성화 상태 확인
|
|
const isUserDisabled = (user) => {
|
|
return props.projctSeq ? user.PROJCTYON === '0' : user.disabled;
|
|
};
|
|
|
|
// 클릭 시 활성화/비활성화 및 DB 업데이트
|
|
const toggleDisable = async (index) => {
|
|
const user = sortedUserList.value[index];
|
|
if (user) {
|
|
const newParticipationStatus = props.projctSeq
|
|
? user.PROJCTYON === '1'
|
|
: !user.disabled;
|
|
if (props.projctSeq) {
|
|
const response = await $api.patch('project/updateYon', {
|
|
memberSeq: user.MEMBERSEQ,
|
|
projctSeq: props.projctSeq,
|
|
projctYon: newParticipationStatus ? '0' : '1'
|
|
});
|
|
if (response.status === 200) {
|
|
// 원래 userList에서 해당 사용자를 찾아 업데이트
|
|
const originalIndex = userList.value.findIndex(u => u.MEMBERSEQ === user.MEMBERSEQ);
|
|
if (originalIndex !== -1) {
|
|
userList.value[originalIndex].PROJCTYON = newParticipationStatus ? '0' : '1';
|
|
}
|
|
}
|
|
} else {
|
|
// 원래 userList에서 해당 사용자를 찾아 업데이트
|
|
const originalIndex = userList.value.findIndex(u => u.MEMBERSEQ === user.MEMBERSEQ);
|
|
if (originalIndex !== -1) {
|
|
userList.value[originalIndex].disabled = newParticipationStatus;
|
|
emitUserListUpdate();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
// emit
|
|
const emitUserListUpdate = () => {
|
|
const activeUsers = userList.value.filter(user => !isUserDisabled(user));
|
|
const disabledUsers = userList.value.filter(user => isUserDisabled(user));
|
|
emit('user-list-update', { activeUsers, disabledUsers });
|
|
};
|
|
|
|
const getTooltipTitle = (user) => {
|
|
return user.MEMBERSEQ === userStore.userInfo.id ? '나' : user.MEMBERNAM;
|
|
};
|
|
</script>
|