123 lines
3.6 KiB
Vue
123 lines
3.6 KiB
Vue
<template>
|
|
<div class="">
|
|
<ul class="row gx-2 mb-2 list-inline">
|
|
<li
|
|
v-for="(user, index) in sortedUserList"
|
|
:key="index"
|
|
class="col-4 mb-3"
|
|
:class="{ newRow: (index + 1) % 4 === 0 }"
|
|
@click="$emit('profileClick', user)"
|
|
data-bs-placement="top"
|
|
:aria-label="user.MEMBERSEQ"
|
|
>
|
|
<div class="ratio ratio-1x1 mb-2">
|
|
<img
|
|
class="rounded-circle profile-img"
|
|
:src="getUserProfileImage(user.MEMBERPRF)"
|
|
alt="user"
|
|
:style="getDynamicStyle(user)"
|
|
@error="setDefaultImage"
|
|
@load="showImage"
|
|
/>
|
|
</div>
|
|
<span class="mt-2 text-sm-center d-block fs-6 remaining-vacation">
|
|
{{ remainingVacationData[user.MEMBERSEQ] || 0 }}
|
|
</span>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { onMounted, ref, computed, nextTick } from "vue";
|
|
import { useUserInfoStore } from "@s/useUserInfoStore";
|
|
import { useUserStore } from "@s/userList";
|
|
import $api from "@api";
|
|
|
|
defineEmits(["profileClick"]);
|
|
defineProps({ remainingVacationData: Object });
|
|
|
|
const userStore = useUserInfoStore();
|
|
const userListStore = useUserStore();
|
|
|
|
const userList = ref([]);
|
|
const baseUrl = $api.defaults.baseURL.replace(/api\/$/, "");
|
|
const defaultProfile = "/img/icons/icon.png";
|
|
const employeeId = ref(null);
|
|
const userColors = ref({});
|
|
const windowWidth = ref(window.innerWidth);
|
|
|
|
const updateWindowWidth = () => {
|
|
windowWidth.value = window.innerWidth;
|
|
};
|
|
|
|
onMounted(async () => {
|
|
window.addEventListener("resize", updateWindowWidth);
|
|
|
|
await userStore.userInfo();
|
|
employeeId.value = userStore.user?.id ?? null;
|
|
|
|
await userListStore.fetchUserList();
|
|
userList.value = userListStore.userList;
|
|
|
|
userList.value.forEach(user => {
|
|
userColors.value[user.MEMBERSEQ] = user.usercolor || "#ccc";
|
|
});
|
|
|
|
nextTick(() => {
|
|
document.querySelectorAll('[data-bs-toggle="tooltip"]').forEach(tooltip => {
|
|
new bootstrap.Tooltip(tooltip);
|
|
});
|
|
});
|
|
});
|
|
|
|
const sortedUserList = computed(() => {
|
|
if (!employeeId.value) return [];
|
|
|
|
// 관리자가 아닌 사용자만 필터링
|
|
const nonAdminUsers = userList.value.filter(user => user.MEMBERROL !== "ROLE_ADMIN");
|
|
|
|
const myProfile = nonAdminUsers.find(user => user.MEMBERSEQ === employeeId.value);
|
|
const otherUsers = nonAdminUsers.filter(user => user.MEMBERSEQ !== employeeId.value);
|
|
|
|
return myProfile ? [myProfile, ...otherUsers] : otherUsers;
|
|
});
|
|
|
|
|
|
const getUserProfileImage = (profilePath) =>
|
|
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 (windowWidth.value >= 1850) {
|
|
if (totalUsers <= 10) return "80px";
|
|
if (totalUsers <= 15) return "60px";
|
|
return "45px";
|
|
} else if (windowWidth.value >= 1500) {
|
|
if (totalUsers <= 10) return "60px";
|
|
if (totalUsers <= 15) return "40px";
|
|
return "30px";
|
|
} else if (windowWidth.value >= 900) {
|
|
if (totalUsers <= 10) return "48px";
|
|
if (totalUsers <= 15) return "30px";
|
|
return "20px";
|
|
} else {
|
|
return "35px";
|
|
}
|
|
});
|
|
|
|
const getDynamicStyle = (user) => ({
|
|
borderWidth: "2px",
|
|
borderColor: user.usercolor || "#ccc",
|
|
borderStyle: "solid",
|
|
});
|
|
</script>
|
|
|
|
<style scoped>
|
|
</style>
|