localhost-front/src/components/vacation/ProfileList.vue
2025-02-18 10:32:49 +09:00

127 lines
3.5 KiB
Vue

<template>
<div class="card-body d-flex justify-content-center">
<ul class="list-unstyled d-flex align-items-center gap-3 mb-0 mt-2">
<li
v-for="(user, index) in sortedUserList"
:key="index"
:class="{ disabled: user.disabled }"
@click="$emit('profileClick', user)"
data-bs-placement="top"
:aria-label="user.MEMBERSEQ"
>
<img
class="rounded-circle user-avatar "
:src="getUserProfileImage(user.MEMBERPRF)"
alt="user"
:style="getDynamicStyle(user)"
@error="setDefaultImage"
@load="showImage"
/>
<span class="remaining-vacation">
{{ remainingVacationData[user.MEMBERSEQ] || 0 }}
</span>
</li>
</ul>
</div>
</template>
<script setup>
import { onMounted, ref, computed, nextTick } from "vue";
import { useUserStore } from "@s/useUserStore";
import { useUserStore as useUserListStore } from "@s/userList";
import $api from "@api";
defineEmits(["profileClick"]);
defineProps({
remainingVacationData: Object,
});
const userStore = useUserInfoStore();
const userListStore = useUserListStore();
const userList = ref([]);
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, "");
const defaultProfile = "/img/icons/icon.png";
const employeeId = ref(null);
const userColors = ref({});
onMounted(async () => {
await userStore.userInfo();
if (userStore.user) {
employeeId.value = userStore.user.id;
} else {
console.error("❌ 로그인한 사용자 정보를 불러오지 못했습니다.");
}
await userListStore.fetchUserList();
userList.value = userListStore.userList;
// 사용자별 색상 저장
userList.value.forEach(user => {
userColors.value[user.MEMBERSEQ] = user.usercolor || "#ccc";
});
nextTick(() => {
const tooltips = document.querySelectorAll('[data-bs-toggle="tooltip"]');
tooltips.forEach(tooltip => {
new bootstrap.Tooltip(tooltip);
});
});
});
const sortedUserList = computed(() => {
if (!employeeId.value) return userList.value; // 로그인한 사용자가 없으면 기존 리스트 반환
const myProfile = userList.value.find(user => user.MEMBERSEQ === employeeId.value);
const otherUsers = userList.value.filter(user => user.MEMBERSEQ !== employeeId.value);
return myProfile ? [myProfile, ...otherUsers] : userList.value;
});
const getUserProfileImage = (profilePath) => {
return profilePath && profilePath.trim()
? `${baseUrl}upload/img/profile/${profilePath}`
: defaultProfile;
};
const setDefaultImage = (event) => {
event.target.src = defaultProfile;
};
const showImage = (event) => {
event.target.style.visibility = "visible";
};
// 프로필 크기 동적 조정
const profileSize = computed(() => {
const totalUsers = userList.value.length;
if (totalUsers <= 7) return "120px"; // 7명 이하
if (totalUsers <= 10) return "100px"; // ~10명
if (totalUsers <= 20) return "80px"; // ~20명
return "60px"; // 20명 이상
});
// 개별 유저 스타일 적용
const getDynamicStyle = (user) => {
return {
width: profileSize.value,
height: profileSize.value,
borderWidth: "4px",
borderColor: user.usercolor || "#ccc",
borderStyle: "solid",
};
};
</script>
<style scoped>
/* 남은 연차 개수 스타일 */
.remaining-vacation {
display: block;
text-align: center;
font-size: 14px;
color: #333;
margin-top: 5px;
}
</style>