localhost-front/src/components/vacation/ProfileList.vue
dyhj625 68607e3d1f
All checks were successful
LocalNet_front/pipeline/head This commit looks good
.
2025-03-31 11:02:54 +09:00

109 lines
3.2 KiB
Vue

<template>
<ul class="row gx-2 mb-0 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-0 profile-list position-relative">
<img
v-if="user.MEMBERSEQ === employeeId"
src="/img/icons/Crown.png"
alt="Crown"
class="start-50 translate-middle crown-icon"
/>
<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>
</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 myProfile = userList.value.find(user => user.MEMBERSEQ === employeeId.value);
const otherUsers = userList.value.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 getDynamicStyle = (user) => ({
borderWidth: "3px",
borderColor: user.usercolor || "#ccc",
borderStyle: "solid",
});
</script>
<style scoped>
.crown-icon {
width: 90%;
height: 70%;
z-index: 0;
top: -7%
}
</style>