프로젝트 참여자 관련 수정
This commit is contained in:
parent
86602d7ffe
commit
90d21869b3
@ -23,7 +23,7 @@
|
|||||||
<div class="d-flex flex-sm-row align-items-center pb-2">
|
<div class="d-flex 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" :showOnlyActive="isProjectExpired" class="ms-8 mb-0" />
|
<UserList ref="userListRef" :projctSeq="projctSeq" :showOnlyActive="true" class="ms-8 mb-0" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 설명 -->
|
<!-- 설명 -->
|
||||||
<div class="d-flex flex-sm-row align-items-center pb-2">
|
<div class="d-flex flex-sm-row align-items-center pb-2">
|
||||||
@ -110,11 +110,26 @@
|
|||||||
:is-essential="true"
|
:is-essential="true"
|
||||||
:is-label="true"
|
:is-label="true"
|
||||||
:is-common="true"
|
:is-common="true"
|
||||||
|
:is-color="true"
|
||||||
:data="allColors"
|
:data="allColors"
|
||||||
:value="selectedProject.PROJCTCOL"
|
:value="selectedProject.PROJCTCOL"
|
||||||
@update:data="selectedProject.PROJCTCOL = $event"
|
@update:data="selectedProject.PROJCTCOL = $event"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div class="mb-2 row">
|
||||||
|
<label class="col-md-2 col-form-label">
|
||||||
|
참여자
|
||||||
|
</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<UserList class="m-0"
|
||||||
|
ref="editUserListRef"
|
||||||
|
:projctSeq="projctSeq"
|
||||||
|
:showOnlyActive="false"
|
||||||
|
@user-list-update="handleEditUserListUpdate"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormInput
|
<FormInput
|
||||||
title="시작일"
|
title="시작일"
|
||||||
type="date"
|
type="date"
|
||||||
@ -161,7 +176,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { defineProps, onMounted, ref, computed, watch } from 'vue';
|
import { defineProps, onMounted, ref, computed, watch, nextTick } 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';
|
||||||
@ -230,6 +245,10 @@ const props = defineProps({
|
|||||||
projctCreatorId: {
|
projctCreatorId: {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: false
|
required: false
|
||||||
|
},
|
||||||
|
resetUserSelection: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -252,6 +271,20 @@ const originalColor = ref('');
|
|||||||
const nameAlert = ref(false);
|
const nameAlert = ref(false);
|
||||||
const user = ref(null);
|
const user = ref(null);
|
||||||
|
|
||||||
|
const editUserListRef = ref(null);
|
||||||
|
const userListRef = ref(null);
|
||||||
|
|
||||||
|
const selectedUsers = ref({
|
||||||
|
activeUsers: [],
|
||||||
|
disabledUsers: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// 사용자 목록 업데이트 핸들러
|
||||||
|
const handleEditUserListUpdate = (userLists) => {
|
||||||
|
selectedUsers.value = userLists;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
const isProjectCreator = computed(() => {
|
const isProjectCreator = computed(() => {
|
||||||
return user.value?.id === props.projctCreatorId;
|
return user.value?.id === props.projctCreatorId;
|
||||||
});
|
});
|
||||||
@ -326,7 +359,7 @@ const closeModal = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 수정 모달 열기
|
// 수정 모달 열기
|
||||||
const openEditModal = () => {
|
const openEditModal = async () => {
|
||||||
selectedProject.value = {
|
selectedProject.value = {
|
||||||
PROJCTSEQ: props.projctSeq,
|
PROJCTSEQ: props.projctSeq,
|
||||||
PROJCTNAM: props.title,
|
PROJCTNAM: props.title,
|
||||||
@ -342,6 +375,7 @@ const openEditModal = () => {
|
|||||||
|
|
||||||
isEditModalOpen.value = true;
|
isEditModalOpen.value = true;
|
||||||
originalColor.value = props.projctCol;
|
originalColor.value = props.projctCol;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// 수정 모달 닫기
|
// 수정 모달 닫기
|
||||||
@ -360,11 +394,17 @@ const closeEditModal = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
isEditModalOpen.value = false;
|
isEditModalOpen.value = false;
|
||||||
|
|
||||||
|
// UserList의 resetSelection 메서드 호출
|
||||||
|
if (editUserListRef.value) {
|
||||||
|
editUserListRef.value.resetSelection();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 변경된 내용 있는지 확인
|
// 변경된 내용 있는지 확인
|
||||||
const hasChanges = computed(() => {
|
const hasChanges = computed(() => {
|
||||||
return selectedProject.value.PROJCTNAM !== props.title ||
|
// 기존 변경 확인 코드
|
||||||
|
const basicChanges = selectedProject.value.PROJCTNAM !== props.title ||
|
||||||
selectedProject.value.PROJCTSTR !== props.strdate ||
|
selectedProject.value.PROJCTSTR !== props.strdate ||
|
||||||
selectedProject.value.PROJCTEND !== props.enddate ||
|
selectedProject.value.PROJCTEND !== props.enddate ||
|
||||||
selectedProject.value.PROJCTZIP !== props.addressZip ||
|
selectedProject.value.PROJCTZIP !== props.addressZip ||
|
||||||
@ -372,6 +412,11 @@ const hasChanges = computed(() => {
|
|||||||
selectedProject.value.PROJCTDTL !== props.addressdtail ||
|
selectedProject.value.PROJCTDTL !== props.addressdtail ||
|
||||||
selectedProject.value.PROJCTDES !== props.description ||
|
selectedProject.value.PROJCTDES !== props.description ||
|
||||||
selectedProject.value.PROJCTCOL !== props.projctCol;
|
selectedProject.value.PROJCTCOL !== props.projctCol;
|
||||||
|
|
||||||
|
const userChanges = selectedUsers.value.activeUsers.length > 0 ||
|
||||||
|
selectedUsers.value.disabledUsers.length > 0;
|
||||||
|
|
||||||
|
return basicChanges || userChanges;
|
||||||
});
|
});
|
||||||
|
|
||||||
// 시작일 또는 종료일이 변경될 때 종료일의 최소값을 설정
|
// 시작일 또는 종료일이 변경될 때 종료일의 최소값을 설정
|
||||||
@ -385,9 +430,15 @@ watch(
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// resetUserSelection 변경 감지
|
||||||
|
watch(() => props.resetUserSelection, () => {
|
||||||
|
if (editUserListRef.value) {
|
||||||
|
editUserListRef.value.resetSelection();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// 프로젝트 수정
|
// 프로젝트 수정
|
||||||
const handleUpdate = () => {
|
const handleUpdate = async () => {
|
||||||
nameAlert.value = selectedProject.value.PROJCTNAM.trim() === '';
|
nameAlert.value = selectedProject.value.PROJCTNAM.trim() === '';
|
||||||
|
|
||||||
if (nameAlert.value) {
|
if (nameAlert.value) {
|
||||||
@ -399,7 +450,9 @@ const handleUpdate = () => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$api.patch('project/update', {
|
const disabledMemberSeqs = selectedUsers.value.disabledUsers.map(user => user.MEMBERSEQ);
|
||||||
|
|
||||||
|
const res = await $api.patch('project/update', {
|
||||||
projctSeq: selectedProject.value.PROJCTSEQ,
|
projctSeq: selectedProject.value.PROJCTSEQ,
|
||||||
projctNam: selectedProject.value.PROJCTNAM,
|
projctNam: selectedProject.value.PROJCTNAM,
|
||||||
projctCol: selectedProject.value.PROJCTCOL,
|
projctCol: selectedProject.value.PROJCTCOL,
|
||||||
@ -411,17 +464,22 @@ const handleUpdate = () => {
|
|||||||
projctDes: selectedProject.value.PROJCTDES || null,
|
projctDes: selectedProject.value.PROJCTDES || null,
|
||||||
projctUmb: user.value?.id,
|
projctUmb: user.value?.id,
|
||||||
originalColor: originalColor.value === selectedProject.value.PROJCTCOL ? null : originalColor.value,
|
originalColor: originalColor.value === selectedProject.value.PROJCTCOL ? null : originalColor.value,
|
||||||
}).then(res => {
|
disabledMembers: disabledMemberSeqs
|
||||||
if (res.status === 200) {
|
|
||||||
toastStore.onToast('수정이 완료 되었습니다.', 's');
|
|
||||||
closeEditModal();
|
|
||||||
|
|
||||||
projectStore.getProjectList();
|
|
||||||
projectStore.getMemberProjects();
|
|
||||||
|
|
||||||
emit('update');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (res.status === 200) {
|
||||||
|
toastStore.onToast('수정이 완료 되었습니다.', 's');
|
||||||
|
|
||||||
|
// 프로젝트 목록 새로고침
|
||||||
|
await projectStore.getProjectList();
|
||||||
|
await projectStore.getMemberProjects();
|
||||||
|
|
||||||
|
await editUserListRef.value.fetchProjectParticipation();
|
||||||
|
await userListRef.value.fetchProjectParticipation();
|
||||||
|
|
||||||
|
closeEditModal();
|
||||||
|
emit('update');
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// 주소를 좌표로 변환하는 함수
|
// 주소를 좌표로 변환하는 함수
|
||||||
|
|||||||
@ -24,6 +24,7 @@
|
|||||||
:projctCol="post.PROJCTCOL"
|
:projctCol="post.PROJCTCOL"
|
||||||
:projctColor="post.projctcolor"
|
:projctColor="post.projctcolor"
|
||||||
:projctCreatorId="post.PROJCTCMB"
|
:projctCreatorId="post.PROJCTCMB"
|
||||||
|
:resetUserSelection="resetUserSelection"
|
||||||
@update="getProjectList"
|
@update="getProjectList"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@ -55,6 +56,19 @@
|
|||||||
@update:data="color = $event"
|
@update:data="color = $event"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<div class="mb-2 row">
|
||||||
|
<label class="col-md-2 col-form-label">
|
||||||
|
참여자
|
||||||
|
</label>
|
||||||
|
<div class="col-md-10">
|
||||||
|
<UserList
|
||||||
|
ref="userListRef"
|
||||||
|
@user-list-update="handleUserListUpdate"
|
||||||
|
class="m-0"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<FormInput
|
<FormInput
|
||||||
title="시작 일"
|
title="시작 일"
|
||||||
name="startDay"
|
name="startDay"
|
||||||
@ -93,14 +107,14 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #footer>
|
<template #footer>
|
||||||
<BackButton type="reset" @click="closeCreateModal" />
|
<BackButton type="reset" @click="closeCreateModal" />
|
||||||
<SaveButton @click="handleCreate" />
|
<SaveButton :disabled="!color" @click="handleCreate" />
|
||||||
</template>
|
</template>
|
||||||
</CenterModal>
|
</CenterModal>
|
||||||
</form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import { computed, ref, watch, onMounted, inject } from 'vue';
|
import { computed, ref, watch, onMounted, inject, nextTick } from 'vue';
|
||||||
import SearchBar from '@c/search/SearchBar.vue';
|
import SearchBar from '@c/search/SearchBar.vue';
|
||||||
import ProjectCard from '@c/list/ProjectCard.vue';
|
import ProjectCard from '@c/list/ProjectCard.vue';
|
||||||
import CategoryBtn from '@/components/category/CategoryBtn.vue';
|
import CategoryBtn from '@/components/category/CategoryBtn.vue';
|
||||||
@ -109,6 +123,7 @@
|
|||||||
import FormSelect from '@c/input/FormSelect.vue';
|
import FormSelect from '@c/input/FormSelect.vue';
|
||||||
import FormInput from '@c/input/FormInput.vue';
|
import FormInput from '@c/input/FormInput.vue';
|
||||||
import ArrInput from '@c/input/ArrInput.vue';
|
import ArrInput from '@c/input/ArrInput.vue';
|
||||||
|
import UserList from '@c/user/UserList.vue';
|
||||||
import commonApi from '@/common/commonApi';
|
import commonApi from '@/common/commonApi';
|
||||||
import { useToastStore } from '@s/toastStore';
|
import { useToastStore } from '@s/toastStore';
|
||||||
import { useUserInfoStore } from '@/stores/useUserInfoStore';
|
import { useUserInfoStore } from '@/stores/useUserInfoStore';
|
||||||
@ -126,6 +141,9 @@
|
|||||||
const selectedCategory = ref(null);
|
const selectedCategory = ref(null);
|
||||||
const searchText = ref('');
|
const searchText = ref('');
|
||||||
|
|
||||||
|
const userListRef = ref(null);
|
||||||
|
const resetUserSelection = ref(false);
|
||||||
|
|
||||||
// dayjs 인스턴스 가져오기
|
// dayjs 인스턴스 가져오기
|
||||||
const dayjs = inject('dayjs');
|
const dayjs = inject('dayjs');
|
||||||
|
|
||||||
@ -149,6 +167,17 @@
|
|||||||
detailAddress: ''
|
detailAddress: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 선택된 사용자 목록 관리
|
||||||
|
const selectedUsers = ref({
|
||||||
|
activeUsers: [],
|
||||||
|
disabledUsers: []
|
||||||
|
});
|
||||||
|
|
||||||
|
// UserList 컴포넌트에서 사용자 선택 업데이트 처리
|
||||||
|
const handleUserListUpdate = (userLists) => {
|
||||||
|
selectedUsers.value = userLists;
|
||||||
|
};
|
||||||
|
|
||||||
// API 호출
|
// API 호출
|
||||||
const { yearCategory, colorList } = commonApi({
|
const { yearCategory, colorList } = commonApi({
|
||||||
loadColor: true,
|
loadColor: true,
|
||||||
@ -172,7 +201,7 @@
|
|||||||
|
|
||||||
// 프로젝트 목록 조회
|
// 프로젝트 목록 조회
|
||||||
const getProjectList = async () => {
|
const getProjectList = async () => {
|
||||||
await projectStore.getProjectList(searchText.value, selectedYear.value);
|
await projectStore.getProjectList(searchText.value, selectedYear.value, 'false');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 카테고리 변경 감지
|
// 카테고리 변경 감지
|
||||||
@ -187,11 +216,12 @@
|
|||||||
|
|
||||||
const closeCreateModal = () => {
|
const closeCreateModal = () => {
|
||||||
isCreateModalOpen.value = false;
|
isCreateModalOpen.value = false;
|
||||||
|
resetUserSelection.value = !resetUserSelection.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formReset = () => {
|
const formReset = () => {
|
||||||
name.value = '';
|
name.value = '';
|
||||||
color.value = '';
|
color.value = colorList.value.length > 0 ? colorList.value[0].value : '';
|
||||||
addressData.value = {
|
addressData.value = {
|
||||||
postcode: '',
|
postcode: '',
|
||||||
address: '',
|
address: '',
|
||||||
@ -201,13 +231,22 @@
|
|||||||
endDay.value = '';
|
endDay.value = '';
|
||||||
description.value = '';
|
description.value = '';
|
||||||
nameAlert.value = false;
|
nameAlert.value = false;
|
||||||
addressAlert.value = false;
|
|
||||||
}
|
selectedUsers.value = {
|
||||||
|
activeUsers: [],
|
||||||
|
disabledUsers: []
|
||||||
|
};
|
||||||
|
|
||||||
|
if (userListRef.value) {
|
||||||
|
userListRef.value.resetSelection();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// 등록 :: 주소 업데이트 핸들러
|
// 등록 :: 주소 업데이트 핸들러
|
||||||
const handleAddressUpdate = (data) => {
|
const handleAddressUpdate = (data) => {
|
||||||
addressData.value = data;
|
addressData.value = data;
|
||||||
} ;
|
};
|
||||||
|
|
||||||
// 시작일이 종료일보다 크면 종료일 리셋
|
// 시작일이 종료일보다 크면 종료일 리셋
|
||||||
watch(startDay, (newStartDate) => {
|
watch(startDay, (newStartDate) => {
|
||||||
@ -216,9 +255,9 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// 프로젝트 등록
|
// 프로젝트 등록
|
||||||
const handleCreate = async () => {
|
const handleCreate = async () => {
|
||||||
|
|
||||||
nameAlert.value = name.value.trim() === '';
|
nameAlert.value = name.value.trim() === '';
|
||||||
addressAlert.value = addressData.value.address.trim() === '';
|
addressAlert.value = addressData.value.address.trim() === '';
|
||||||
|
|
||||||
@ -226,8 +265,10 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$api.post('project/insert', {
|
// 비활성화된 사용자 목록 생성
|
||||||
|
const disabledMemberSeqs = selectedUsers.value.disabledUsers.map(user => user.MEMBERSEQ);
|
||||||
|
|
||||||
|
const response = await $api.post('project/insert', {
|
||||||
projctNam: name.value,
|
projctNam: name.value,
|
||||||
projctCol: color.value,
|
projctCol: color.value,
|
||||||
projctStr: startDay.value,
|
projctStr: startDay.value,
|
||||||
@ -237,15 +278,17 @@
|
|||||||
projctDtl: addressData.value.detailAddress,
|
projctDtl: addressData.value.detailAddress,
|
||||||
projctZip: addressData.value.postcode,
|
projctZip: addressData.value.postcode,
|
||||||
projctCmb: user.value.id,
|
projctCmb: user.value.id,
|
||||||
}).then(res => {
|
disabledMembers: disabledMemberSeqs
|
||||||
if (res.status === 200) {
|
|
||||||
toastStore.onToast('프로젝트가 등록되었습니다.', 's');
|
|
||||||
closeCreateModal();
|
|
||||||
getProjectList();
|
|
||||||
projectStore.getMemberProjects();
|
|
||||||
formReset();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (response.status === 200) {
|
||||||
|
toastStore.onToast('프로젝트가 등록되었습니다.', 's');
|
||||||
|
closeCreateModal();
|
||||||
|
getProjectList();
|
||||||
|
projectStore.getMemberProjects();
|
||||||
|
formReset();
|
||||||
|
resetUserSelection.value = !resetUserSelection.value;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
|
|||||||
@ -54,6 +54,28 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const resetSelection = async () => {
|
||||||
|
// 모든 사용자를 활성화 상태로 초기화
|
||||||
|
if (props.projctSeq) {
|
||||||
|
// 프로젝트 수정 모드일 경우
|
||||||
|
userList.value = userList.value.map(user => ({
|
||||||
|
...user,
|
||||||
|
PROJCTYON: '1'
|
||||||
|
}));
|
||||||
|
|
||||||
|
// 프로젝트 참여 정보 다시 가져오기
|
||||||
|
await fetchProjectParticipation();
|
||||||
|
} else {
|
||||||
|
// 프로젝트 생성 모드일 경우
|
||||||
|
userList.value = userList.value.map(user => ({
|
||||||
|
...user,
|
||||||
|
disabled: false // 모든 사용자 활성화
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
emitUserListUpdate();
|
||||||
|
};
|
||||||
|
|
||||||
// 활성화된 회원을 앞으로 정렬하는 computed 속성
|
// 활성화된 회원을 앞으로 정렬하는 computed 속성
|
||||||
const sortedUserList = computed(() => {
|
const sortedUserList = computed(() => {
|
||||||
return [...userList.value].sort((a, b) => {
|
return [...userList.value].sort((a, b) => {
|
||||||
@ -85,6 +107,7 @@ const fetchProjectParticipation = async () => {
|
|||||||
...user,
|
...user,
|
||||||
PROJCTYON: projectMembers.find(pm => pm.MEMBERSEQ === user.MEMBERSEQ)?.PROJCTYON ?? '1'
|
PROJCTYON: projectMembers.find(pm => pm.MEMBERSEQ === user.MEMBERSEQ)?.PROJCTYON ?? '1'
|
||||||
}));
|
}));
|
||||||
|
emitUserListUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -104,8 +127,9 @@ const fetchUserProjectPeriods = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// projctSeq가 변경될 때마다 참여 기간 데이터 다시 불러오기
|
// projctSeq가 변경될 때마다 참여 기간 데이터 다시 불러오기
|
||||||
watch(() => props.projctSeq, async (newVal) => {
|
watch(() => props.projctSeq, async (newVal, oldVal) => {
|
||||||
if (newVal) {
|
if (newVal !== oldVal) {
|
||||||
|
await fetchProjectParticipation();
|
||||||
await fetchUserProjectPeriods();
|
await fetchUserProjectPeriods();
|
||||||
}
|
}
|
||||||
}, { immediate: true });
|
}, { immediate: true });
|
||||||
@ -118,6 +142,9 @@ onMounted(async () => {
|
|||||||
if (props.projctSeq) {
|
if (props.projctSeq) {
|
||||||
await fetchProjectParticipation();
|
await fetchProjectParticipation();
|
||||||
await fetchUserProjectPeriods();
|
await fetchUserProjectPeriods();
|
||||||
|
} else {
|
||||||
|
// projctSeq가 없는 경우, 초기 상태 emit
|
||||||
|
emitUserListUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
nextTick(() => {
|
nextTick(() => {
|
||||||
@ -136,55 +163,34 @@ const initTooltips = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 사용자 비활성화 상태 확인
|
// 사용자 비활성화 상태 확인
|
||||||
const isUserDisabled = (user) => {
|
const isUserDisabled = (user) => {
|
||||||
return props.projctSeq ? user.PROJCTYON === '0' : user.disabled;
|
return props.projctSeq ? user.PROJCTYON === '0' : user.disabled;
|
||||||
};
|
};
|
||||||
|
|
||||||
// 클릭 시 활성화/비활성화 및 DB 업데이트
|
// 사용자 선택 토글 (즉시 API 호출 없이 상태만 변경)
|
||||||
// showOnlyActive가 true일 때는 toggleDisable 함수가 실행되지 않음
|
const toggleDisable = (index) => {
|
||||||
const toggleDisable = async (index) => {
|
|
||||||
if (props.showOnlyActive) return;
|
if (props.showOnlyActive) return;
|
||||||
const user = displayedUserList.value[index];
|
const user = displayedUserList.value[index];
|
||||||
|
|
||||||
// 본인 계정이면 비활성화 방지
|
// 본인 계정이면 비활성화 방지
|
||||||
if (props.role === 'vote') {
|
if (props.role === 'vote') {
|
||||||
if(user.MEMBERSEQ === userStore.userInfo.id) {
|
if (user.MEMBERSEQ === userStore.userInfo.id) {
|
||||||
toastStore.onToast('본인은 비활성화할 수 없습니다.', 'e');
|
toastStore.onToast('본인은 비활성화할 수 없습니다.', 'e');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (user) {
|
if (user) {
|
||||||
const newParticipationStatus = props.projctSeq
|
// 프로젝트 수정 모드인 경우
|
||||||
? user.PROJCTYON === '1'
|
|
||||||
: !user.disabled;
|
|
||||||
if (props.projctSeq) {
|
if (props.projctSeq) {
|
||||||
const response = await $api.patch('project/updateYon', {
|
user.PROJCTYON = user.PROJCTYON === '1' ? '0' : '1';
|
||||||
memberSeq: user.MEMBERSEQ,
|
|
||||||
projctSeq: props.projctSeq,
|
|
||||||
projctYon: newParticipationStatus ? '0' : '1'
|
|
||||||
});
|
|
||||||
if (response.status === 200) {
|
|
||||||
// 원래 userList에서 해당 사용자를 찾아 업데이트
|
|
||||||
const originalIndex = userList.value.findIndex(u => u.MEMBERSEQ === user.MEMBERSEQ);
|
|
||||||
if (originalIndex !== -1) {
|
|
||||||
userList.value[originalIndex].PROJCTYON = newParticipationStatus ? '0' : '1';
|
|
||||||
}
|
|
||||||
|
|
||||||
// 변경 후 프로젝트 목록 새로고침
|
|
||||||
const projectStore = useProjectStore();
|
|
||||||
await projectStore.getProjectList('', '', 'true');
|
|
||||||
await projectStore.getMemberProjects();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// 원래 userList에서 해당 사용자를 찾아 업데이트
|
user.disabled = !user.disabled;
|
||||||
const originalIndex = userList.value.findIndex(u => u.MEMBERSEQ === user.MEMBERSEQ);
|
|
||||||
if (originalIndex !== -1) {
|
|
||||||
userList.value[originalIndex].disabled = newParticipationStatus;
|
|
||||||
emitUserListUpdate();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
emitUserListUpdate();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -216,5 +222,10 @@ const getTooltipTitle = (user) => {
|
|||||||
|
|
||||||
return userName;
|
return userName;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
defineExpose({
|
||||||
|
resetSelection, fetchProjectParticipation
|
||||||
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|||||||
@ -10,13 +10,13 @@
|
|||||||
<ul class="navbar-nav flex-row align-items-center ms-auto">
|
<ul class="navbar-nav flex-row align-items-center ms-auto">
|
||||||
<select class="form-select py-1" id="name" v-model="selectedProject" @change="updateSelectedProject">
|
<select class="form-select py-1" id="name" v-model="selectedProject" @change="updateSelectedProject">
|
||||||
<!-- 내가 참여하고 있는 프로젝트 그룹 -->
|
<!-- 내가 참여하고 있는 프로젝트 그룹 -->
|
||||||
<option v-for="item in myProjects" :key="item.PROJCTSEQ" :value="item.PROJCTSEQ">
|
<option v-for="item in myActiveProjects" :key="item.PROJCTSEQ" :value="item.PROJCTSEQ">
|
||||||
{{ item.PROJCTNAM }}
|
{{ item.PROJCTNAM }}
|
||||||
</option>
|
</option>
|
||||||
<!-- 전체 프로젝트 그룹 -->
|
<!-- 내가 참여하지 않는 프로젝트 그룹 -->
|
||||||
<option disabled>-----------</option>
|
<option disabled>-----------</option>
|
||||||
<option v-for="item in otherProjects" :key="item.PROJCTSEQ" :value="item.PROJCTSEQ">
|
<option v-for="item in otherActiveProjects" :key="item.PROJCTSEQ" :value="item.PROJCTSEQ">
|
||||||
{{ item.PROJCTNAM }}
|
{{ item.PROJCTNAM }}
|
||||||
</option>
|
</option>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
@ -262,28 +262,28 @@
|
|||||||
const user = ref(null);
|
const user = ref(null);
|
||||||
const selectedProject = ref(null);
|
const selectedProject = ref(null);
|
||||||
|
|
||||||
// 내가 참여하고 있는 프로젝트 목록
|
// 내가 참여하고 있는 진행 중인 프로젝트 목록
|
||||||
const myProjects = computed(() => {
|
const myActiveProjects = computed(() => {
|
||||||
return projectStore.memberProjectList || [];
|
return projectStore.activeMemberProjectList || [];
|
||||||
});
|
});
|
||||||
|
|
||||||
// 내가 참여하고 있지 않은 프로젝트 목록
|
// 내가 참여하고 있지 않은 진행 중인 프로젝트 목록
|
||||||
const otherProjects = computed(() => {
|
const otherActiveProjects = computed(() => {
|
||||||
if (!projectStore.projectList || !projectStore.memberProjectList) return [];
|
if (!projectStore.activeProjectList) return [];
|
||||||
|
|
||||||
// 내 프로젝트 ID 목록
|
// 내 프로젝트 ID 목록
|
||||||
const myProjectIds = projectStore.memberProjectList.map(p => p.PROJCTSEQ);
|
const myProjectIds = myActiveProjects.value.map(p => p.PROJCTSEQ);
|
||||||
|
|
||||||
// 내 프로젝트가 아닌 프로젝트만 필터링
|
// 내 프로젝트가 아닌 프로젝트만 필터링
|
||||||
return projectStore.projectList.filter(p => !myProjectIds.includes(p.PROJCTSEQ));
|
return projectStore.activeProjectList.filter(p => !myProjectIds.includes(p.PROJCTSEQ));
|
||||||
});
|
});
|
||||||
|
|
||||||
// 프로젝트 선택 변경 시 스토어에 저장
|
// 프로젝트 선택 변경 시 스토어에 저장
|
||||||
const updateSelectedProject = () => {
|
const updateSelectedProject = () => {
|
||||||
if (!selectedProject.value) return;
|
if (!selectedProject.value) return;
|
||||||
|
|
||||||
// 전체 프로젝트 리스트에서 선택된 프로젝트 찾기
|
// 모든 진행 중인 프로젝트 리스트에서 선택된 프로젝트 찾기
|
||||||
const selected = projectStore.projectList.find(
|
let selected = projectStore.activeProjectList.find(
|
||||||
project => project.PROJCTSEQ === selectedProject.value
|
project => project.PROJCTSEQ === selectedProject.value
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -312,21 +312,21 @@
|
|||||||
await userStore.userInfo();
|
await userStore.userInfo();
|
||||||
user.value = userStore.user;
|
user.value = userStore.user;
|
||||||
|
|
||||||
if (authStore.isAuthenticated) {
|
|
||||||
await projectStore.getProjectList('', '', 'true');
|
await projectStore.loadAllProjectLists();
|
||||||
}
|
|
||||||
|
|
||||||
// 사용자가 참여하고 있는 프로젝트 목록
|
// 사용자가 참여하고 있는 프로젝트 목록
|
||||||
await projectStore.getMemberProjects();
|
await projectStore.getMemberProjects();
|
||||||
|
|
||||||
|
|
||||||
// 저장된 선택 프로젝트
|
// 저장된 선택 프로젝트
|
||||||
const storedProject = projectStore.getSelectedProject();
|
const storedProject = projectStore.getSelectedProject();
|
||||||
if (storedProject) {
|
if (storedProject) {
|
||||||
selectedProject.value = storedProject.PROJCTSEQ;
|
selectedProject.value = storedProject.PROJCTSEQ;
|
||||||
} else if (projectStore.memberProjectList.length > 0) {
|
} else if (projectStore.activeMemberProjectList.length > 0) {
|
||||||
// 저장된 선택 프로젝트가 없으면 첫 번째 참여 프로젝트 선택
|
// 저장된 선택 프로젝트가 없으면 첫 번째 참여 프로젝트 선택
|
||||||
selectedProject.value = projectStore.memberProjectList[0].PROJCTSEQ;
|
selectedProject.value = projectStore.activeMemberProjectList[0].PROJCTSEQ;
|
||||||
projectStore.setSelectedProject(projectStore.memberProjectList[0]);
|
projectStore.setSelectedProject(projectStore.activeMemberProjectList[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -9,15 +9,20 @@ import { defineStore } from 'pinia';
|
|||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import $api from '@api';
|
import $api from '@api';
|
||||||
import { useUserInfoStore } from '@/stores/useUserInfoStore';
|
import { useUserInfoStore } from '@/stores/useUserInfoStore';
|
||||||
|
import { useAuthStore } from '@/stores/useAuthStore';
|
||||||
|
|
||||||
export const useProjectStore = defineStore('project', () => {
|
export const useProjectStore = defineStore('project', () => {
|
||||||
const projectList = ref([]);
|
const projectList = ref([]); // 모든 프로젝트 (종료된 프로젝트 포함)
|
||||||
const memberProjectList = ref([]);
|
const activeProjectList = ref([]); // 진행 중인 프로젝트만 (종료된 프로젝트 제외)
|
||||||
|
const memberProjectList = ref([]); // 사용자가 속한 프로젝트
|
||||||
|
const activeMemberProjectList = ref([]); // 사용자가 속한 진행 중인 프로젝트
|
||||||
const selectedProject = ref(null);
|
const selectedProject = ref(null);
|
||||||
const userStore = useUserInfoStore();
|
const userStore = useUserInfoStore();
|
||||||
|
const authStore = useAuthStore();
|
||||||
|
|
||||||
// 전체 프로젝트 가져오기
|
// 전체 프로젝트 가져오기 (종료된 프로젝트 포함 여부에 따라 다른 배열에 저장)
|
||||||
const getProjectList = async (searchText = '', selectedYear = '', excludeEnded = '') => {
|
const getProjectList = async (searchText = '', selectedYear = '', excludeEnded = 'false') => {
|
||||||
|
if (!userStore.user) return;
|
||||||
const res = await $api.get('project/select', {
|
const res = await $api.get('project/select', {
|
||||||
params: {
|
params: {
|
||||||
searchKeyword: searchText || '',
|
searchKeyword: searchText || '',
|
||||||
@ -25,7 +30,22 @@ export const useProjectStore = defineStore('project', () => {
|
|||||||
excludeEnded: excludeEnded
|
excludeEnded: excludeEnded
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
projectList.value = res.data.data.projectList;
|
|
||||||
|
if (excludeEnded === 'true') {
|
||||||
|
// 종료되지 않은 프로젝트만 저장
|
||||||
|
activeProjectList.value = res.data.data.projectList;
|
||||||
|
} else {
|
||||||
|
// 모든 프로젝트 저장 (종료된 프로젝트 포함)
|
||||||
|
projectList.value = res.data.data.projectList;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 모든 프로젝트 목록 로드 (종료 여부 구분하여 모두 로드)
|
||||||
|
const loadAllProjectLists = async (searchText = '', selectedYear = '') => {
|
||||||
|
// 진행 중인 프로젝트 로드
|
||||||
|
await getProjectList(searchText, selectedYear, 'true');
|
||||||
|
// 모든 프로젝트 로드 (종료된 프로젝트 포함)
|
||||||
|
await getProjectList(searchText, selectedYear, 'false');
|
||||||
};
|
};
|
||||||
|
|
||||||
// 사용자가 속한 프로젝트 목록 가져오기
|
// 사용자가 속한 프로젝트 목록 가져오기
|
||||||
@ -33,10 +53,16 @@ export const useProjectStore = defineStore('project', () => {
|
|||||||
if (!userStore.user) return; // 로그인한 사용자 확인
|
if (!userStore.user) return; // 로그인한 사용자 확인
|
||||||
|
|
||||||
const res = await $api.get(`project/${userStore.user.id}`);
|
const res = await $api.get(`project/${userStore.user.id}`);
|
||||||
memberProjectList.value = res.data.data;
|
const allMemberProjects = res.data.data;
|
||||||
|
memberProjectList.value = allMemberProjects;
|
||||||
|
|
||||||
if (memberProjectList.value.length > 0 && !selectedProject.value) {
|
// 사용자가 속한 프로젝트 중 진행 중인 프로젝트만 필터링
|
||||||
setSelectedProject(memberProjectList.value[0]);
|
activeMemberProjectList.value = allMemberProjects.filter(project =>
|
||||||
|
!project.ENDYN || project.ENDYN === 'N'
|
||||||
|
);
|
||||||
|
|
||||||
|
if (activeMemberProjectList.value.length > 0 && !selectedProject.value) {
|
||||||
|
setSelectedProject(activeMemberProjectList.value[0]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -60,19 +86,19 @@ export const useProjectStore = defineStore('project', () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// 프로젝트 리스트가 변경될 때 자동으로 반응
|
// 프로젝트 리스트가 변경될 때 자동으로 반응
|
||||||
watch(projectList, (newList) => {
|
watch(activeProjectList, (newList) => {
|
||||||
// 선택된 프로젝트가 없고 목록이 있는 경우
|
// 선택된 프로젝트가 없고 목록이 있는 경우
|
||||||
if (!selectedProject.value && newList.length > 0) {
|
if (!selectedProject.value && newList.length > 0) {
|
||||||
// 사용자가 속한 프로젝트가 있는지 먼저 확인
|
// 사용자가 속한 프로젝트가 있는지 먼저 확인
|
||||||
if (memberProjectList.value.length > 0) {
|
if (activeMemberProjectList.value.length > 0) {
|
||||||
setSelectedProject(memberProjectList.value[0]);
|
setSelectedProject(activeMemberProjectList.value[0]);
|
||||||
} else {
|
} else {
|
||||||
setSelectedProject(newList[0]);
|
setSelectedProject(newList[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(memberProjectList, (newList) => {
|
watch(activeMemberProjectList, (newList) => {
|
||||||
if (newList.length > 0) {
|
if (newList.length > 0) {
|
||||||
// 현재 선택된 프로젝트가 없는 경우 첫 번째 항목 선택
|
// 현재 선택된 프로젝트가 없는 경우 첫 번째 항목 선택
|
||||||
if (!selectedProject.value) {
|
if (!selectedProject.value) {
|
||||||
@ -88,14 +114,16 @@ export const useProjectStore = defineStore('project', () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
projectList,
|
projectList, // 종료된 프로젝트 포함한 모든 프로젝트
|
||||||
|
activeProjectList, // 진행 중인 프로젝트만
|
||||||
|
memberProjectList, // 사용자가 속한 모든 프로젝트
|
||||||
|
activeMemberProjectList, // 사용자가 속한 진행 중인 프로젝트
|
||||||
selectedProject,
|
selectedProject,
|
||||||
getProjectList,
|
getProjectList,
|
||||||
memberProjectList,
|
loadAllProjectLists, // 모든 프로젝트 목록 한번에 로드
|
||||||
getMemberProjects,
|
getMemberProjects,
|
||||||
setSelectedProject,
|
setSelectedProject,
|
||||||
getSelectedProject
|
getSelectedProject,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user