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