250328_work
This commit is contained in:
parent
c4ff151581
commit
a540feb851
@ -47,11 +47,11 @@ const common = {
|
|||||||
*
|
*
|
||||||
* @param {string} dateStr
|
* @param {string} dateStr
|
||||||
* @return
|
* @return
|
||||||
* 1. Date type 인 경우 예시 '25-02-24 12:02'
|
* 1. Date type 인 경우 예시 '2025-02-24 12:02'
|
||||||
* 2. Date type 이 아닌 경우 입력값 리턴
|
* 2. Date type 이 아닌 경우 입력값 리턴
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
dateFormatter(dateStr) {
|
dateFormatter(dateStr, type = null) {
|
||||||
const date = new Date(dateStr);
|
const date = new Date(dateStr);
|
||||||
const dateCheck = date.getTime();
|
const dateCheck = date.getTime();
|
||||||
|
|
||||||
@ -59,13 +59,26 @@ const common = {
|
|||||||
return dateStr;
|
return dateStr;
|
||||||
} else {
|
} else {
|
||||||
const { year, month, day, hours, minutes } = this.formatDateTime(date);
|
const { year, month, day, hours, minutes } = this.formatDateTime(date);
|
||||||
return `${year}-${month}-${day} ${hours}:${minutes}`;
|
let callback = '';
|
||||||
|
|
||||||
|
if (type == 'YMD') {
|
||||||
|
callback = `${year}-${month}-${day}`;
|
||||||
|
} else if (type == 'MD') {
|
||||||
|
callback = `${month}-${day}`;
|
||||||
|
} else {
|
||||||
|
callback = `${year}-${month}-${day} ${hours}:${minutes}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return callback;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
formatDateTime(date) {
|
formatDateTime(dateObj) {
|
||||||
const zeroFormat = num => (num < 10 ? `0${num}` : num);
|
const date = new Date(dateObj);
|
||||||
|
const dateCheck = date.getTime();
|
||||||
|
if (isNaN(dateCheck)) return dateStr;
|
||||||
|
|
||||||
|
const zeroFormat = num => (num < 10 ? `0${num}` : num);
|
||||||
return {
|
return {
|
||||||
year: date.getFullYear(),
|
year: date.getFullYear(),
|
||||||
month: zeroFormat(date.getMonth() + 1),
|
month: zeroFormat(date.getMonth() + 1),
|
||||||
|
|||||||
@ -140,34 +140,6 @@
|
|||||||
todaysCommuter();
|
todaysCommuter();
|
||||||
};
|
};
|
||||||
|
|
||||||
// 프로젝트 드롭 이벤트 핸들러 (ProjectList 컴포넌트에서 전달받음)
|
|
||||||
const handleProjectDrop = ({ event, targetProject }) => {
|
|
||||||
// 드래그된 프로젝트 데이터 가져오기
|
|
||||||
const draggedProjectData = JSON.parse(event.dataTransfer.getData('application/json'));
|
|
||||||
|
|
||||||
// 드래그한 프로젝트와 드롭한 프로젝트가 같으면 아무 동작 안 함
|
|
||||||
if (draggedProjectData.PROJCTSEQ === targetProject.PROJCTSEQ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 선택된 프로젝트 변경
|
|
||||||
checkedInProject.value = targetProject;
|
|
||||||
projectStore.setSelectedProject(targetProject);
|
|
||||||
|
|
||||||
// select 값도 변경
|
|
||||||
selectedProject.value = targetProject.PROJCTSEQ;
|
|
||||||
|
|
||||||
$api.patch('commuters/update', {
|
|
||||||
projctSeq: targetProject.PROJCTSEQ,
|
|
||||||
memberSeq: user.value.id,
|
|
||||||
}).then(res => {
|
|
||||||
if (res.status === 200) {
|
|
||||||
todaysCommuter();
|
|
||||||
loadCommuters();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
// 오늘 출근 모든 사용자 조회
|
// 오늘 출근 모든 사용자 조회
|
||||||
const todaysCommuter = async () => {
|
const todaysCommuter = async () => {
|
||||||
const res = await $api.get(`commuters/todays`);
|
const res = await $api.get(`commuters/todays`);
|
||||||
@ -195,14 +167,85 @@
|
|||||||
const { data } = await $api.get(`main/eventList?${param}`);
|
const { data } = await $api.get(`main/eventList?${param}`);
|
||||||
const res = data?.data;
|
const res = data?.data;
|
||||||
|
|
||||||
|
// 기존의 공휴일 이벤트는 유지
|
||||||
|
const holidayEvents = calendarEvents.value.filter(event => event.classNames?.includes('holiday-event'));
|
||||||
|
calendarEvents.value = [...holidayEvents];
|
||||||
|
|
||||||
// 생일자
|
// 생일자
|
||||||
if (res?.memberBirthdayList?.length) monthBirthdayList.value = [...res.memberBirthdayList];
|
if (res?.memberBirthdayList?.length) {
|
||||||
|
monthBirthdayList.value = [...res.memberBirthdayList];
|
||||||
|
res.memberBirthdayList.forEach(member => {
|
||||||
|
addEvent($common.dateFormatter(member.MEMBERBTH, 'YMD'), 'birthday', `${member.MEMBERNAM}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// 휴가자
|
// 휴가자
|
||||||
if (res?.memberVacationList?.length) monthVacationList.value = [...res.memberVacationList];
|
if (res?.memberVacationList?.length) {
|
||||||
|
monthVacationList.value = [...res.memberVacationList];
|
||||||
|
res.memberVacationList.forEach(member => {
|
||||||
|
addEvent($common.dateFormatter(member.LOCVACUDT, 'YMD'), 'vacation', `${member.MEMBERNAM}`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 생일파티
|
||||||
|
if (res?.birthdayPartyList?.length) {
|
||||||
|
res.birthdayPartyList.forEach(party => {
|
||||||
|
addEvent(party.EVENTDT, 'birthdayParty', '생일파티');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 회식
|
||||||
|
if (res?.dinnerList?.length) {
|
||||||
|
res.dinnerList.forEach(dinner => {
|
||||||
|
addEvent(dinner.EVENTDT, 'dinner', '회식');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 티타임
|
||||||
|
if (res?.teaTimeList?.length) {
|
||||||
|
res.teaTimeList.forEach(tea => {
|
||||||
|
addEvent(tea.EVENTDT, 'teaTime', '티타임');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 워크샵
|
||||||
|
if (res?.workshopList?.length) {
|
||||||
|
res.workshopList.forEach(workshop => {
|
||||||
|
addEvent(workshop.EVENTDT, 'workshop', '워크샵');
|
||||||
|
});
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 해당일 기준 이벤트 리스트
|
// 달력에 이벤트 데이터 추가
|
||||||
|
const addEvent = (date, type, title) => {
|
||||||
|
// 생일의 경우 달력의 현재 년도로 변경하여 처리
|
||||||
|
if (type === 'birthday') {
|
||||||
|
const calendarApi = fullCalendarRef.value?.getApi();
|
||||||
|
if (calendarApi) {
|
||||||
|
const dateArr = calendarApi.currentData.viewTitle.split(' ');
|
||||||
|
const calendarYear = parseInt(dateArr[0].replace(/\D/g, ''), 10);
|
||||||
|
const birthDate = $common.dateFormatter(date, 'MD');
|
||||||
|
date = `${calendarYear}-${birthDate}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 같은 날짜와 타입의 이벤트가 이미 있는지 확인
|
||||||
|
const existingEvent = calendarEvents.value.find(
|
||||||
|
event => $common.dateFormatter(event.start, 'MD') === $common.dateFormatter(date, 'MD') && event.type == type,
|
||||||
|
);
|
||||||
|
|
||||||
|
// 없는 경우에만 추가
|
||||||
|
if (!existingEvent) {
|
||||||
|
calendarEvents.value.push({
|
||||||
|
start: date,
|
||||||
|
type: type,
|
||||||
|
title: title,
|
||||||
|
classNames: [`${type}-event`],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 해당일 기준 이벤트 리스트 필터링
|
||||||
const useFilterEventList = (month, day) => {
|
const useFilterEventList = (month, day) => {
|
||||||
// 생일자
|
// 생일자
|
||||||
if (monthBirthdayList.value) {
|
if (monthBirthdayList.value) {
|
||||||
@ -234,13 +277,14 @@
|
|||||||
try {
|
try {
|
||||||
// 현재 표시 중인 월의 공휴일 정보 가져오기
|
// 현재 표시 중인 월의 공휴일 정보 가져오기
|
||||||
const holidayEvents = await fetchHolidays(currentYear, String(currentMonth).padStart(2, '0'));
|
const holidayEvents = await fetchHolidays(currentYear, String(currentMonth).padStart(2, '0'));
|
||||||
// 기존 이벤트에서 공휴일 이벤트를 제외한 이벤트만 필터링
|
calendarEvents.value = [...holidayEvents]; // 공휴일 정보로 초기화
|
||||||
const existingEvents = calendarEvents.value.filter(event => !event.classNames?.includes('holiday-event'));
|
|
||||||
// 필터링된 이벤트와 새로 가져온 공휴일 이벤트 병합
|
|
||||||
calendarEvents.value = [...existingEvents, ...holidayEvents];
|
|
||||||
|
|
||||||
// 출근 정보
|
// 이벤트 데이터 가져오기
|
||||||
await loadCommuters();
|
const param = new URLSearchParams();
|
||||||
|
param.append('year', currentYear);
|
||||||
|
param.append('month', currentMonth);
|
||||||
|
param.append('day', '1'); // 해당 월의 첫날
|
||||||
|
await fetchEventList(param);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('공휴일 정보 로딩 실패:', error);
|
console.error('공휴일 정보 로딩 실패:', error);
|
||||||
}
|
}
|
||||||
@ -274,47 +318,81 @@
|
|||||||
return !isWeekend && !isHoliday;
|
return !isWeekend && !isHoliday;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 날짜 클릭 이벤트 함수
|
// 이벤트 타입 정의
|
||||||
let todayElement = null;
|
const eventTypes = [
|
||||||
|
{ type: 'birthdayParty', code: '300203', title: '생일파티' },
|
||||||
|
{ type: 'dinner', code: '300204', title: '회식' },
|
||||||
|
{ type: 'teaTime', code: '300205', title: '티타임' },
|
||||||
|
{ type: 'workshop', code: '300206', title: '워크샵' },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 날짜 클릭 이벤트 함수 수정
|
||||||
const handleDateClick = info => {
|
const handleDateClick = info => {
|
||||||
const clickedDate = dayjs(info.date).format('YYYY-MM-DD');
|
// const clickedDate = dayjs(info.dateStr);
|
||||||
|
const { month, day } = $common.formatDateTime(new Date(info.dateStr));
|
||||||
|
|
||||||
// 클릭한 날짜에 월별 출근 정보가 있는지 확인
|
// 클릭한 날짜의 이벤트 리스트 필터링
|
||||||
const dateCommuters = monthlyCommuters.value.filter(commuter => commuter.COMMUTDAY === clickedDate);
|
useFilterEventList(month, day);
|
||||||
|
|
||||||
// 출근 기록이 있는 경우에만 모달 열기
|
// 팝오버 HTML 생성
|
||||||
if (dateCommuters.length > 0) {
|
const popoverContent = `
|
||||||
eventDate.value = clickedDate;
|
<div class="d-flex flex-wrap gap-2 p-2">
|
||||||
isModalOpen.value = true;
|
${eventTypes
|
||||||
}
|
.map(
|
||||||
|
event => `
|
||||||
|
<img
|
||||||
|
src="${baseUrl}img/main-category-img/main-${event.code}.png"
|
||||||
|
class="event-icon-select"
|
||||||
|
data-event-type="${event.type}"
|
||||||
|
data-event-title="${event.title}"
|
||||||
|
data-date="${info.dateStr}"
|
||||||
|
style="width: 25px; height: 25px; cursor: pointer;"
|
||||||
|
/>
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
.join('')}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
if (isSelectableDate(info.date)) {
|
// 기존 팝오버 제거
|
||||||
const isToday = dayjs(info.date).isSame(dayjs(), 'day');
|
const existingPopovers = document.querySelectorAll('.event-popover');
|
||||||
|
existingPopovers.forEach(popover => popover.remove());
|
||||||
|
|
||||||
if (isToday) {
|
// 새 팝오버 생성
|
||||||
// 오늘 날짜 클릭 시 클래스 제거하고 요소 저장
|
const popover = document.createElement('div');
|
||||||
todayElement = info.dayEl;
|
popover.className = 'event-popover position-absolute bg-white shadow rounded z-3';
|
||||||
todayElement.classList.remove('fc-day-today');
|
popover.innerHTML = popoverContent;
|
||||||
} else if (todayElement) {
|
popover.style.top = `${info.jsEvent.pageY}px`;
|
||||||
// 다른 날짜 클릭 시 저장된 오늘 요소에 클래스 다시 추가
|
popover.style.left = `${info.jsEvent.pageX}px`;
|
||||||
todayElement.classList.add('fc-day-today');
|
|
||||||
todayElement = null;
|
// 아이콘 클릭 이벤트 추가
|
||||||
|
popover.addEventListener('click', e => {
|
||||||
|
const target = e.target;
|
||||||
|
if (target.classList.contains('event-icon-select')) {
|
||||||
|
const eventType = target.dataset.eventType;
|
||||||
|
const eventTitle = target.dataset.eventTitle;
|
||||||
|
const date = target.dataset.date;
|
||||||
|
|
||||||
|
// 이벤트 추가
|
||||||
|
addEvent(date, eventType, eventTitle);
|
||||||
|
|
||||||
|
// 팝오버 닫기
|
||||||
|
popover.remove();
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
// 문서에 팝오버 추가
|
||||||
|
document.body.appendChild(popover);
|
||||||
|
|
||||||
|
// 팝오버 외부 클릭 시 닫기
|
||||||
|
document.addEventListener('click', e => {
|
||||||
|
if (!e.target.closest('.event-popover') && !e.target.closest('.fc-daygrid-day')) {
|
||||||
|
const popovers = document.querySelectorAll('.event-popover');
|
||||||
|
popovers.forEach(p => p.remove());
|
||||||
|
}
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// 바깥 클릭 시 todayElement 클래스 복구
|
|
||||||
document.addEventListener(
|
|
||||||
'click',
|
|
||||||
event => {
|
|
||||||
if (todayElement && !event.target.closest('.fc-daygrid-day')) {
|
|
||||||
todayElement.classList.add('fc-day-today');
|
|
||||||
todayElement = null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
true,
|
|
||||||
);
|
|
||||||
|
|
||||||
// 날짜 셀 클래스 추가 함수
|
// 날짜 셀 클래스 추가 함수
|
||||||
const getCellClassNames = arg => {
|
const getCellClassNames = arg => {
|
||||||
const cellDate = dayjs(arg.date);
|
const cellDate = dayjs(arg.date);
|
||||||
@ -379,6 +457,50 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 이벤트 아이콘 표시 함수
|
||||||
|
const handleEventContent = item => {
|
||||||
|
if (!item.event) return null;
|
||||||
|
|
||||||
|
// 공휴일인 경우 텍스트로 표시
|
||||||
|
if (item.event.classNames?.includes('holiday-event')) {
|
||||||
|
return {
|
||||||
|
html: `<div class="holiday-text" style="color: white;">${item.event.title}</div>`,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// 현재 이벤트의 타입만 확인
|
||||||
|
const eventType = item.event.extendedProps.type;
|
||||||
|
if (!eventType) return null;
|
||||||
|
|
||||||
|
let iconCode = '';
|
||||||
|
switch (eventType) {
|
||||||
|
case 'birthday':
|
||||||
|
iconCode = '300201';
|
||||||
|
break;
|
||||||
|
case 'vacation':
|
||||||
|
iconCode = '300202';
|
||||||
|
break;
|
||||||
|
case 'birthdayParty':
|
||||||
|
iconCode = '300203';
|
||||||
|
break;
|
||||||
|
case 'dinner':
|
||||||
|
iconCode = '300204';
|
||||||
|
break;
|
||||||
|
case 'teaTime':
|
||||||
|
iconCode = '300205';
|
||||||
|
break;
|
||||||
|
case 'workshop':
|
||||||
|
iconCode = '300206';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
html: `<img src="${baseUrl}img/main-category-img/main-${iconCode}.png" class="calendar-event-icon" style="width: 20px; height: 20px; margin: 2px;" />`,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
// 캘린더 옵션 설정
|
// 캘린더 옵션 설정
|
||||||
const calendarOptions = reactive({
|
const calendarOptions = reactive({
|
||||||
plugins: [dayGridPlugin, interactionPlugin],
|
plugins: [dayGridPlugin, interactionPlugin],
|
||||||
@ -392,19 +514,14 @@
|
|||||||
events: calendarEvents,
|
events: calendarEvents,
|
||||||
eventOrder: 'sortIdx',
|
eventOrder: 'sortIdx',
|
||||||
contentHeight: 'auto',
|
contentHeight: 'auto',
|
||||||
// eventContent: calendarCommuter,
|
eventContent: handleEventContent,
|
||||||
// 날짜 선택 관련 옵션 수정
|
|
||||||
selectable: true,
|
selectable: true,
|
||||||
selectAllow: selectInfo => isSelectableDate(selectInfo.start),
|
selectAllow: selectInfo => isSelectableDate(selectInfo.start),
|
||||||
dateClick: handleDateClick,
|
dateClick: handleDateClick,
|
||||||
dayCellClassNames: getCellClassNames,
|
dayCellClassNames: getCellClassNames,
|
||||||
|
|
||||||
// 날짜 클릭 비활성화를 위한 추가 설정
|
|
||||||
unselectAuto: true,
|
unselectAuto: true,
|
||||||
droppable: false,
|
droppable: false,
|
||||||
eventDisplay: 'block',
|
eventDisplay: 'block',
|
||||||
|
|
||||||
// 커스텀 버튼 정의
|
|
||||||
customButtons: {
|
customButtons: {
|
||||||
prev: {
|
prev: {
|
||||||
text: 'PREV',
|
text: 'PREV',
|
||||||
@ -470,9 +587,6 @@
|
|||||||
checkedInProject.value = storedProject;
|
checkedInProject.value = storedProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 이벤트 카테고리 호출
|
|
||||||
await fetchCategoryList();
|
|
||||||
|
|
||||||
// 오늘 기준 데이터 호출
|
// 오늘 기준 데이터 호출
|
||||||
const { year, month, day } = $common.getToday();
|
const { year, month, day } = $common.getToday();
|
||||||
const param = new URLSearchParams();
|
const param = new URLSearchParams();
|
||||||
@ -480,7 +594,24 @@
|
|||||||
param.append('month', month);
|
param.append('month', month);
|
||||||
param.append('day', day);
|
param.append('day', day);
|
||||||
|
|
||||||
|
// 이벤트 카테고리 호출
|
||||||
|
await fetchCategoryList();
|
||||||
await fetchEventList(param);
|
await fetchEventList(param);
|
||||||
useFilterEventList(month, day);
|
useFilterEventList(month, day);
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<style>
|
||||||
|
.fc-h-event {
|
||||||
|
background-color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-popover {
|
||||||
|
padding: 8px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
.event-icon-select:hover {
|
||||||
|
transform: scale(1.1);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
@ -1,7 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="">
|
<div class="">
|
||||||
<template v-for="category in categoryList" :key="category.CMNCODVAL">
|
<template v-for="category in categoryList" :key="category.CMNCODVAL">
|
||||||
<div class="border border-2 mt-3 card p-2">
|
<div
|
||||||
|
v-if="(category.CMNCODVAL === 300201 && birthdayList?.length) || (category.CMNCODVAL === 300202 && vacationList?.length)"
|
||||||
|
class="border border-2 mt-3 card p-2"
|
||||||
|
>
|
||||||
<div class="row g-2">
|
<div class="row g-2">
|
||||||
<div class="col-3 mx-0 px-0">
|
<div class="col-3 mx-0 px-0">
|
||||||
<div class="ratio ratio-1x1">
|
<div class="ratio ratio-1x1">
|
||||||
@ -14,36 +17,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-9 mx-0 px-0">
|
<div class="col-9 mx-0 px-0">
|
||||||
<template v-if="category.CMNCODVAL === 300201">
|
<template v-if="category.CMNCODVAL === 300201">
|
||||||
<div class="ms-2">
|
<MainMemberProfile :members="birthdayList" :baseUrl="baseUrl" />
|
||||||
<ul class="row gx-1 mb-0 list-inline d-flex align-items-center">
|
|
||||||
<li class="col-4 me-0" v-for="member in birthdayList" :key="member.MEMBERSEQ">
|
|
||||||
<div class="ratio ratio-1x1 mb-0 profile-list">
|
|
||||||
<img
|
|
||||||
:src="`${baseUrl}upload/img/profile/${member.MEMBERPRF}`"
|
|
||||||
alt="User Profile"
|
|
||||||
class="rounded-circle"
|
|
||||||
@error="$event.target.src = '/img/icons/icon.png'"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-if="category.CMNCODVAL === 300202">
|
<template v-if="category.CMNCODVAL === 300202">
|
||||||
<div class="ms-2">
|
<MainMemberProfile :members="vacationList" :baseUrl="baseUrl" />
|
||||||
<ul class="row gx-1 mb-0 list-inline d-flex align-items-center">
|
|
||||||
<li class="col-4 me-0" v-for="member in vacationList" :key="member.MEMBERSEQ">
|
|
||||||
<div class="ratio ratio-1x1 mb-0 profile-list">
|
|
||||||
<img
|
|
||||||
:src="`${baseUrl}upload/img/profile/${member.MEMBERPRF}`"
|
|
||||||
alt="User Profile"
|
|
||||||
class="rounded-circle"
|
|
||||||
@error="$event.target.src = '/img/icons/icon.png'"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -54,6 +31,7 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineEmits } from 'vue';
|
import { defineEmits } from 'vue';
|
||||||
|
import MainMemberProfile from '@c/main/MainMemberProfile.vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
project: {
|
project: {
|
||||||
|
|||||||
31
src/components/main/MainMemberProfile.vue
Normal file
31
src/components/main/MainMemberProfile.vue
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
<template>
|
||||||
|
<div class="ms-2">
|
||||||
|
<ul class="row gx-1 mb-0 list-inline d-flex align-items-center">
|
||||||
|
<li class="col-4 me-0" v-for="(member, index) in members" :key="index">
|
||||||
|
<div class="ratio ratio-1x1 mb-0 profile-list">
|
||||||
|
<img
|
||||||
|
:src="`${baseUrl}upload/img/profile/${member.MEMBERPRF}`"
|
||||||
|
alt="User Profile"
|
||||||
|
class="rounded-circle"
|
||||||
|
@error="$event.target.src = '/img/icons/icon.png'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
members: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
baseUrl: {
|
||||||
|
type: String,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<MainCalendar />
|
<MainEventCalendar />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import MainCalendar from '@/components/main/MainEventCalendar.vue';
|
import MainEventCalendar from '@/components/main/MainEventCalendar.vue';
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user