339 lines
11 KiB
Vue
339 lines
11 KiB
Vue
<template>
|
|
<SearchBar @update:data="search" />
|
|
<div class="d-flex align-items-center">
|
|
<CategoryBtn :lists="yearCategory" @update:data="selectedCategory = $event" />
|
|
<WriteBtn class="mt-2 ms-auto" @click="openCreateModal" />
|
|
</div>
|
|
|
|
<!-- 프로젝트 목록 -->
|
|
<div class="mt-4">
|
|
<div v-if="projectStore.projectList.length === 0" class="text-center">
|
|
<p class="text-muted mt-4">등록된 프로젝트가 없습니다.</p>
|
|
</div>
|
|
|
|
<div v-for="post in projectStore.projectList" :key="post.PROJCTSEQ">
|
|
<ProjectCard
|
|
:title="post.PROJCTNAM"
|
|
:description="post.PROJCTDES"
|
|
:strdate="post.PROJCTSTR"
|
|
:enddate="post.PROJCTEND"
|
|
:address="post.PROJCTARR"
|
|
:addressdtail="post.PROJCTDTL"
|
|
:addressZip="post.PROJCTZIP"
|
|
:projctSeq="post.PROJCTSEQ"
|
|
:projctCol="post.PROJCTCOL"
|
|
:projctColor="post.projctcolor"
|
|
:projctCreatorId="post.PROJCTCMB"
|
|
:resetUserSelection="resetUserSelection"
|
|
:searchParams="{ text: searchText, year: selectedYear }"
|
|
@update="handleProjectUpdate"
|
|
/>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 등록 모달 -->
|
|
<form @reset.prevent="formReset">
|
|
<CenterModal :display="isCreateModalOpen" @close="closeCreateModal" :create="true" @reset="formReset">
|
|
<template #title> 프로젝트 등록 </template>
|
|
<template #body>
|
|
<FormInput
|
|
title="이름"
|
|
name="name"
|
|
:is-essential="true"
|
|
:is-alert="nameAlert"
|
|
:modelValue="name"
|
|
@update:alert="nameAlert = $event"
|
|
@update:modelValue="name = $event"
|
|
/>
|
|
|
|
<FormSelect
|
|
title="컬러"
|
|
name="color"
|
|
:is-essential="true"
|
|
:is-label="true"
|
|
:is-common="true"
|
|
:is-color="true"
|
|
:value="color"
|
|
:data="colorList"
|
|
@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
|
|
title="시작 일"
|
|
name="startDay"
|
|
:type="'date'"
|
|
:is-alert="startDayAlert"
|
|
:is-essential="true"
|
|
:modelValue="startDay"
|
|
v-model="startDay"
|
|
/>
|
|
|
|
<FormInput
|
|
title="종료 일"
|
|
name="endDay"
|
|
:type="'date'"
|
|
:modelValue="endDay"
|
|
:min="startDay"
|
|
@update:modelValue="endDay = $event"
|
|
/>
|
|
|
|
<FormInput
|
|
title="설명"
|
|
name="description"
|
|
:modelValue="description"
|
|
@update:modelValue="description = $event"
|
|
/>
|
|
|
|
<ArrInput
|
|
title="주소"
|
|
name="address"
|
|
:isEssential="true"
|
|
:is-row="true"
|
|
:is-alert="addressAlert"
|
|
:modelValue="addressData"
|
|
@update:data="handleAddressUpdate"
|
|
@update:alert="addressAlert = $event"
|
|
/>
|
|
</template>
|
|
<template #footer>
|
|
<BackButton type="reset" @click="closeCreateModal" />
|
|
<SaveButton @click="handleCreate" />
|
|
</template>
|
|
</CenterModal>
|
|
</form>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, ref, watch, onMounted, inject, nextTick } from 'vue';
|
|
import SearchBar from '@c/search/SearchBar.vue';
|
|
import ProjectCard from '@c/list/ProjectCard.vue';
|
|
import CategoryBtn from '@/components/category/CategoryBtn.vue';
|
|
import WriteBtn from '@c/button/WriteBtn.vue';
|
|
import CenterModal from '@c/modal/CenterModal.vue';
|
|
import FormSelect from '@c/input/FormSelect.vue';
|
|
import FormInput from '@c/input/FormInput.vue';
|
|
import ArrInput from '@c/input/ArrInput.vue';
|
|
import UserList from '@c/user/UserList.vue';
|
|
import commonApi, { refreshColorList } from '@/common/commonApi';
|
|
import { useToastStore } from '@s/toastStore';
|
|
import { useUserInfoStore } from '@/stores/useUserInfoStore';
|
|
import { useProjectStore } from '@/stores/useProjectStore';
|
|
import $api from '@api';
|
|
import SaveButton from '@c/button/SaveBtn.vue';
|
|
import BackButton from '@c/button/BackBtn.vue';
|
|
|
|
const toastStore = useToastStore();
|
|
const userStore = useUserInfoStore();
|
|
const projectStore = useProjectStore();
|
|
|
|
// 상태 관리
|
|
const user = ref(null);
|
|
const selectedCategory = ref(null);
|
|
const searchText = ref('');
|
|
|
|
const userListRef = ref(null);
|
|
const resetUserSelection = ref(false);
|
|
|
|
// dayjs 인스턴스 가져오기
|
|
const dayjs = inject('dayjs');
|
|
|
|
// 오늘 날짜를 YYYY-MM-DD 형식으로 변환
|
|
const today = dayjs().format('YYYY-MM-DD');
|
|
|
|
// 등록 모달 상태
|
|
const isCreateModalOpen = ref(false);
|
|
const name = ref('');
|
|
const color = ref('0');
|
|
|
|
const startDay = ref(today);
|
|
const endDay = ref('');
|
|
const description = ref('');
|
|
const nameAlert = ref(false);
|
|
const addressAlert = ref(false);
|
|
const startDayAlert = ref(false);
|
|
|
|
|
|
const addressData = ref({
|
|
postcode: '',
|
|
address: '',
|
|
detailAddress: ''
|
|
});
|
|
|
|
// 선택된 사용자 목록 관리
|
|
const selectedUsers = ref({
|
|
activeUsers: [],
|
|
disabledUsers: []
|
|
});
|
|
|
|
// UserList 컴포넌트에서 사용자 선택 업데이트 처리
|
|
const handleUserListUpdate = (userLists) => {
|
|
selectedUsers.value = userLists;
|
|
};
|
|
|
|
// API 호출
|
|
const { yearCategory, colorList } = commonApi({
|
|
loadColor: true,
|
|
colorType: 'YNP',
|
|
loadYearCategory: true,
|
|
});
|
|
|
|
// 검색 처리
|
|
const search = async searchKeyword => {
|
|
searchText.value = searchKeyword.trim();
|
|
await getProjectList();
|
|
};
|
|
|
|
const selectedYear = computed(() => {
|
|
if (!selectedCategory.value || selectedCategory.value === 900101) {
|
|
return null;
|
|
}
|
|
// 선택된 category 값 label 값으로 변환
|
|
return yearCategory.value.find(item => item.value === selectedCategory.value)?.label || null;
|
|
});
|
|
|
|
// 프로젝트 목록 조회
|
|
const getProjectList = async () => {
|
|
await projectStore.getProjectList(searchText.value, selectedYear.value, 'false');
|
|
};
|
|
|
|
// 카테고리 변경 감지
|
|
watch(selectedCategory, async () => {
|
|
await getProjectList();
|
|
});
|
|
|
|
// 등록 모달 관리
|
|
const openCreateModal = async () => {
|
|
const updatedColors = await refreshColorList('YNP');
|
|
|
|
if (updatedColors && updatedColors.length > 0) {
|
|
color.value = updatedColors[0].value;
|
|
}
|
|
|
|
isCreateModalOpen.value = true;
|
|
};
|
|
|
|
const closeCreateModal = () => {
|
|
isCreateModalOpen.value = false;
|
|
resetUserSelection.value = !resetUserSelection.value;
|
|
};
|
|
|
|
const formReset = () => {
|
|
|
|
name.value = '';
|
|
color.value = colorList.value[0].value;
|
|
addressData.value = {
|
|
postcode: '',
|
|
address: '',
|
|
detailAddress: ''
|
|
};
|
|
startDay.value = today;
|
|
endDay.value = '';
|
|
description.value = '';
|
|
nameAlert.value = false;
|
|
addressAlert.value = false;
|
|
startDayAlert.value = false;
|
|
|
|
selectedUsers.value = {
|
|
activeUsers: [],
|
|
disabledUsers: []
|
|
};
|
|
|
|
if (userListRef.value) {
|
|
userListRef.value.resetSelection();
|
|
}
|
|
|
|
};
|
|
|
|
|
|
// 등록 :: 주소 업데이트 핸들러
|
|
const handleAddressUpdate = (data) => {
|
|
addressData.value = data;
|
|
};
|
|
|
|
// 시작일이 종료일보다 크면 종료일 리셋
|
|
watch(startDay, (newStartDate) => {
|
|
if (new Date(newStartDate) > new Date(endDay.value)) {
|
|
endDay.value = '';
|
|
}
|
|
});
|
|
|
|
const handleProjectUpdate = async (params) => {
|
|
if (params) {
|
|
await projectStore.getProjectList(params.text, params.year, 'false');
|
|
} else {
|
|
await projectStore.getProjectList(searchText.value, selectedYear.value, 'false');
|
|
}
|
|
await projectStore.getMemberProjects();
|
|
|
|
// 컬러 목록 새로고침 및 결과 확인
|
|
const updatedColors = await refreshColorList('YNP');
|
|
|
|
// 컬러 선택값 초기화 (필요시)
|
|
if (updatedColors && updatedColors.length > 0) {
|
|
color.value = updatedColors[0].value;
|
|
}
|
|
};
|
|
|
|
// 프로젝트 등록
|
|
const handleCreate = async () => {
|
|
nameAlert.value = name.value.trim() === '';
|
|
startDayAlert.value = startDay.value.trim() === '';
|
|
addressAlert.value = addressData.value.address.trim() === '';
|
|
|
|
if (nameAlert.value || startDayAlert.value || addressAlert.value) {
|
|
return;
|
|
}
|
|
|
|
// 비활성화된 사용자 목록 생성
|
|
const disabledMemberSeqs = selectedUsers.value.disabledUsers.map(user => user.MEMBERSEQ);
|
|
|
|
const response = await $api.post('project/insert', {
|
|
projctNam: name.value,
|
|
projctCol: color.value,
|
|
projctStr: startDay.value,
|
|
projctEnd: endDay.value || null,
|
|
projctDes: description.value || null,
|
|
projctArr: addressData.value.address,
|
|
projctDtl: addressData.value.detailAddress,
|
|
projctZip: addressData.value.postcode,
|
|
projctCmb: user.value.id,
|
|
disabledMembers: disabledMemberSeqs
|
|
});
|
|
|
|
if (response.status === 200) {
|
|
toastStore.onToast('프로젝트가 등록되었습니다.', 's');
|
|
|
|
colorList.value = colorList.value.filter(c => c.value !== color.value);
|
|
|
|
formReset();
|
|
|
|
await getProjectList();
|
|
await projectStore.getMemberProjects();
|
|
|
|
closeCreateModal();
|
|
resetUserSelection.value = !resetUserSelection.value;
|
|
}
|
|
};
|
|
|
|
onMounted(async () => {
|
|
await getProjectList();
|
|
await userStore.userInfo();
|
|
user.value = userStore.user;
|
|
|
|
|
|
});
|
|
</script>
|