종료된 프로젝트 관련
This commit is contained in:
parent
292b479523
commit
cbc3c9dda5
@ -1,16 +1,18 @@
|
||||
<template>
|
||||
<div class="card mb-3 shadow-sm border">
|
||||
<div class="card mb-3 shadow-sm border" :class="isProjectExpired ? 'end-project' : ''">
|
||||
<div class="row g-0">
|
||||
<div class="card-body">
|
||||
<!-- 제목 -->
|
||||
<h5 class="card-title d-flex justify-content-between">
|
||||
<div class="d-flex justify-content-between ">
|
||||
<h5 class="card-title fw-bold">
|
||||
{{ title }}
|
||||
|
||||
<div>
|
||||
<EditBtn @click.stop="openEditModal" />
|
||||
<DeleteBtn @click.stop="handleDelete" class="ms-1"/>
|
||||
</div>
|
||||
</h5>
|
||||
<p v-if="isProjectExpired" class="btn-icon btn-danger rounded-2"><i class='bx bx-power-off'></i></p>
|
||||
<div v-if="!isProjectExpired">
|
||||
<EditBtn @click.stop="openEditModal" />
|
||||
<DeleteBtn v-if="isProjectCreator" @click.stop="handleDelete" class="ms-1"/>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 날짜 -->
|
||||
<div class="d-flex flex-column flex-sm-row align-items-center pb-2">
|
||||
<i class="bx bx-calendar"></i>
|
||||
@ -21,7 +23,7 @@
|
||||
<div class="d-flex flex-column flex-sm-row align-items-center pb-2">
|
||||
<i class="bx bxs-user"></i>
|
||||
<div class="ms-2">참여자</div>
|
||||
<UserList :projctSeq="projctSeq" class="ms-8 mb-0" />
|
||||
<UserList :projctSeq="projctSeq" :showOnlyActive="isProjectExpired" class="ms-8 mb-0" />
|
||||
</div>
|
||||
<!-- 설명 -->
|
||||
<div class="d-flex flex-column flex-sm-row align-items-center pb-2">
|
||||
@ -46,13 +48,18 @@
|
||||
v-if="coordinates"
|
||||
:lat="coordinates.lat"
|
||||
:lng="coordinates.lng"
|
||||
class="w-px-200 h-px-200"
|
||||
class="w-px-250 h-px-200"
|
||||
@onLoadKakaoMap="onLoadKakaoMap"
|
||||
>
|
||||
<KakaoMapMarker
|
||||
:lat="coordinates.lat"
|
||||
:lng="coordinates.lng"
|
||||
/>
|
||||
</KakaoMap>
|
||||
<div class="position-absolute top-50 translate-middle-y end-0 me-3 z-1 d-flex flex-column gap-1">
|
||||
<button class="btn-secondary border-none" @click="zoomOut">+</button>
|
||||
<button class="btn-secondary border-none" @click="zoomIn">-</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -153,7 +160,7 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps, onMounted, ref, computed, inject } from 'vue';
|
||||
import { defineProps, onMounted, ref, computed, watch } from 'vue';
|
||||
import UserList from '@c/user/UserList.vue';
|
||||
import CenterModal from '@c/modal/CenterModal.vue';
|
||||
import $api from '@api';
|
||||
@ -217,6 +224,10 @@ const props = defineProps({
|
||||
type: String,
|
||||
required: false
|
||||
},
|
||||
projctCreatorId: {
|
||||
type: Number,
|
||||
required: false
|
||||
}
|
||||
});
|
||||
|
||||
// Emit 정의
|
||||
@ -228,6 +239,7 @@ const logData = ref([]);
|
||||
|
||||
// 주소 팝오버 상태
|
||||
const isPopoverVisible = ref(false);
|
||||
const map = ref();
|
||||
const mapIconRef = ref(null);
|
||||
const coordinates = ref(null);
|
||||
|
||||
@ -237,6 +249,23 @@ const originalColor = ref('');
|
||||
const nameAlert = ref(false);
|
||||
const user = ref(null);
|
||||
|
||||
const isProjectCreator = computed(() => {
|
||||
return user.value?.id === props.projctCreatorId;
|
||||
});
|
||||
|
||||
// 프로젝트 만료 여부 체크 (종료일이 지났는지)
|
||||
const isProjectExpired = computed(() => {
|
||||
if (!props.enddate) return false;
|
||||
|
||||
const today = new Date();
|
||||
today.setHours(0, 0, 0, 0); // 오늘 날짜의 시작 시간으로 설정
|
||||
|
||||
const endDate = new Date(props.enddate);
|
||||
endDate.setHours(0, 0, 0, 0); // 종료일의 시작 시간으로 설정
|
||||
|
||||
return endDate < today;
|
||||
});
|
||||
|
||||
// 수정할 프로젝트 데이터
|
||||
const selectedProject = ref({
|
||||
PROJCTSEQ: props.projctSeq,
|
||||
@ -273,6 +302,7 @@ const updateAddress = addressData => {
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
// 로그 데이터 가져오기
|
||||
const getLogData = async () => {
|
||||
const res = await $api.get(`project/log/${props.projctSeq}`);
|
||||
@ -295,17 +325,23 @@ const closeModal = () => {
|
||||
const openEditModal = () => {
|
||||
isEditModalOpen.value = true;
|
||||
originalColor.value = props.projctCol;
|
||||
|
||||
// 사용자 정보 가져오기 (필요한 경우)
|
||||
if (!user.value) {
|
||||
userStore.userInfo().then(() => {
|
||||
user.value = userStore.user;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 수정 모달 닫기
|
||||
const closeEditModal = () => {
|
||||
selectedProject.value = {
|
||||
PROJCTSEQ: props.projctSeq,
|
||||
PROJCTNAM: props.title,
|
||||
PROJCTSTR: props.strdate,
|
||||
PROJCTEND: props.enddate,
|
||||
PROJCTZIP: props.addressZip,
|
||||
PROJCTARR: props.address,
|
||||
PROJCTDTL: props.addressdtail,
|
||||
PROJCTDES: props.description,
|
||||
PROJCTCOL: props.projctCol,
|
||||
projctcolor: props.projctColor,
|
||||
};
|
||||
|
||||
isEditModalOpen.value = false;
|
||||
};
|
||||
|
||||
@ -320,6 +356,19 @@ const hasChanges = computed(() => {
|
||||
selectedProject.value.PROJCTDES !== props.description ||
|
||||
selectedProject.value.PROJCTCOL !== props.projctCol;
|
||||
});
|
||||
// 종료일이 시작일보다 이전 날짜라면 종료일을 시작일로 맞추기
|
||||
watch(
|
||||
() => selectedProject.value,
|
||||
() => {
|
||||
const start = new Date(selectedProject.value.PROJCTSTR);
|
||||
const end = new Date(selectedProject.value.PROJCTEND);
|
||||
|
||||
if (end < start) {
|
||||
selectedProject.value.PROJCTEND = selectedProject.value.PROJCTSTR;
|
||||
}
|
||||
},
|
||||
{ deep: true, flush: 'post' }
|
||||
);
|
||||
|
||||
// 프로젝트 수정
|
||||
const handleUpdate = () => {
|
||||
@ -344,7 +393,7 @@ const handleUpdate = () => {
|
||||
projctStr: selectedProject.value.PROJCTSTR,
|
||||
projctEnd: selectedProject.value.PROJCTEND || null,
|
||||
projctDes: selectedProject.value.PROJCTDES || null,
|
||||
projctUmb: user.value?.name,
|
||||
projctUmb: user.value?.id,
|
||||
originalColor: originalColor.value === selectedProject.value.PROJCTCOL ? null : originalColor.value,
|
||||
}).then(res => {
|
||||
if (res.status === 200) {
|
||||
@ -376,6 +425,26 @@ const convertAddressToCoordinates = () => {
|
||||
});
|
||||
};
|
||||
|
||||
const onLoadKakaoMap = (mapRef) => {
|
||||
map.value = mapRef;
|
||||
};
|
||||
|
||||
// 지도 확대
|
||||
const zoomIn = () => {
|
||||
if (map.value) {
|
||||
const level = map.value.getLevel();
|
||||
map.value.setLevel(level + 1);
|
||||
}
|
||||
};
|
||||
|
||||
// 지도 축소
|
||||
const zoomOut = () => {
|
||||
if (map.value) {
|
||||
const level = map.value.getLevel();
|
||||
map.value.setLevel(level - 1);
|
||||
}
|
||||
};
|
||||
|
||||
// 프로젝트 삭제
|
||||
const handleDelete = () => {
|
||||
$api.patch('project/delete', {
|
||||
@ -388,15 +457,16 @@ const handleDelete = () => {
|
||||
location.reload()
|
||||
}
|
||||
})
|
||||
|
||||
};
|
||||
|
||||
// 컴포넌트 마운트 시 실행
|
||||
onMounted(async () => {
|
||||
convertAddressToCoordinates();
|
||||
|
||||
// 사용자 정보 가져오기
|
||||
await userStore.userInfo();
|
||||
user.value = userStore.user;
|
||||
|
||||
convertAddressToCoordinates();
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
:projctSeq="post.PROJCTSEQ"
|
||||
:projctCol="post.PROJCTCOL"
|
||||
:projctColor="post.projctcolor"
|
||||
:projctCreatorId="post.PROJCTCMB"
|
||||
@update="getProjectList"
|
||||
/>
|
||||
</div>
|
||||
@ -205,20 +206,19 @@
|
||||
// 등록 :: 주소 업데이트 핸들러
|
||||
const handleAddressUpdate = (data) => {
|
||||
addressData.value = data;
|
||||
};
|
||||
};
|
||||
|
||||
// 시작일이나 종료일이 변경될 때마다 종료일을 유효성 검사
|
||||
// 종료일이 시작일보다 이전 날짜라면 종료일을 시작일로 맞추기
|
||||
watch([startDay, endDay], () => {
|
||||
if (startDay.value && endDay.value) {
|
||||
const start = new Date(startDay.value);
|
||||
const end = new Date(endDay.value);
|
||||
|
||||
// 종료일이 시작일보다 이전 날짜라면 종료일을 시작일로 맞추기
|
||||
if (end < start) {
|
||||
endDay.value = startDay.value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}, { flush: 'post' });
|
||||
|
||||
// 프로젝트 등록
|
||||
const handleCreate = async () => {
|
||||
@ -240,7 +240,7 @@
|
||||
projctArr: addressData.value.address,
|
||||
projctDtl: addressData.value.detailAddress,
|
||||
projctZip: addressData.value.postcode,
|
||||
projctCmb: user.value.name,
|
||||
projctCmb: user.value.id,
|
||||
}).then(res => {
|
||||
if (res.status === 200) {
|
||||
toastStore.onToast('프로젝트가 등록되었습니다.', 's');
|
||||
|
||||
@ -1,11 +1,12 @@
|
||||
<template>
|
||||
<ul class="list-unstyled users-list d-flex align-items-center gap-1">
|
||||
<li
|
||||
v-for="(user, index) in sortedUserList"
|
||||
v-for="(user, index) in displayedUserList"
|
||||
:key="index"
|
||||
class="avatar pull-up"
|
||||
:class="{ 'opacity-100': isUserDisabled(user) }"
|
||||
@click.stop="toggleDisable(index)"
|
||||
@click.stop="showOnlyActive ? null : toggleDisable(index)"
|
||||
:style="showOnlyActive ? 'cursor: default' : ''"
|
||||
data-bs-toggle="tooltip"
|
||||
data-popup="tooltip-custom"
|
||||
data-bs-placement="top"
|
||||
@ -38,6 +39,10 @@ const props = defineProps({
|
||||
projctSeq: {
|
||||
type: Number,
|
||||
required: false,
|
||||
},
|
||||
showOnlyActive: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
@ -54,6 +59,14 @@ const sortedUserList = computed(() => {
|
||||
});
|
||||
});
|
||||
|
||||
// showOnlyActive가 true면 활성화된 사용자만 표시, 아니면 모든 사용자 표시
|
||||
const displayedUserList = computed(() => {
|
||||
if (props.showOnlyActive) {
|
||||
return sortedUserList.value.filter(user => !isUserDisabled(user));
|
||||
}
|
||||
return sortedUserList.value;
|
||||
});
|
||||
|
||||
// 사용자의 프로젝트 참여 상태 확인
|
||||
const fetchProjectParticipation = async () => {
|
||||
if (props.projctSeq) {
|
||||
@ -91,8 +104,11 @@ const isUserDisabled = (user) => {
|
||||
};
|
||||
|
||||
// 클릭 시 활성화/비활성화 및 DB 업데이트
|
||||
// showOnlyActive가 true일 때는 toggleDisable 함수가 실행되지 않음
|
||||
const toggleDisable = async (index) => {
|
||||
const user = sortedUserList.value[index];
|
||||
if (props.showOnlyActive) return; // showOnlyActive가 true이면 함수 실행 중지
|
||||
|
||||
const user = displayedUserList.value[index];
|
||||
if (user) {
|
||||
const newParticipationStatus = props.projctSeq
|
||||
? user.PROJCTYON === '1'
|
||||
|
||||
Loading…
Reference in New Issue
Block a user