localhost-front/src/views/voteboard/voteboardWrite.vue
2025-03-21 12:19:26 +09:00

247 lines
9.3 KiB
Vue

<template>
<div class="container-xxl flex-grow-1 container-p-y">
<div class="card mb-6">
<div class="card-body">
<div class="user-list-container">
<ul class="timeline mb-1">
<li class="timeline-item timeline-item-transparent">
<span class="timeline-point timeline-point-info"></span>
<div class="timeline-event">
<div class="timeline-header mb-2">
<h6 class="mb-0">투표 인원</h6>
</div>
<UserList :role="'vote'" @userListInfo="userSet" @user-list-update="handleUserListUpdate" class="mb-3" />
<div v-if="UserListAlert" class="invalid-feedback d-block">2명이상 선택해주세요.</div>
<form-input
title="제목"
name="title"
:is-essential="true"
:is-alert="titleAlert"
v-model="title"
@keyup="ValidHandler('title')"
/>
<div class="date-picker-container" @click="focusDateInput">
<form-input
title="종료날짜"
name="endDate"
type="datetime-local"
:is-essential="true"
:is-alert="endDateAlert"
v-model="endDate"
:min="today"
@change="ValidHandlerendDate"
/>
</div>
<!-- 숨겨진 input 태그를 사용하여 강제로 포커스 -->
<input ref="dateInput" type="datetime-local" v-model="endDate" class="hidden-date-input">
<!-- 항목 입력 반복 -->
<div v-for="(item, index) in itemList" :key="index">
<form-input
:title="'항목 ' + (index + 1)"
:name="'content' + index"
:is-essential="index < 2"
:is-alert="contentAlerts[index]"
v-model="item.content"
@keyup="ValidHandler('content' + (index + 1))"
:is-btn="true"
>
<template v-slot:append>
<delete-btn @click="removeItem(index)" :disabled="index < 2" />
</template>
</form-input>
<form-input
:title="'URL ' + (index + 1)"
:name="'url' + index"
v-model="item.url"
:is-essential="false"
class="mb-1"
/>
<!-- <link-input v-model="item.url" class="mb-1"/> -->
</div>
<plus-btn @click="addItem" :disabled="itemList.length >= 10" class="mb-3" />
<div>
<label>
<input
class="form-check-input me-1"
type="checkbox"
id="addvoteitem"
v-model="addvoteitem"
/>
항목 추가여부
</label>
</div>
<div>
<label >
<input
class="form-check-input me-1"
type="checkbox"
id="addvotemulti"
v-model="addvotemulti"
/>
다중투표 허용여부
</label>
</div>
</div>
</li>
</ul>
<div class="mb-4 d-flex justify-content-end">
<button type="button" class="btn btn-info" @click="goList">
<i class="bx bx-left-arrow-alt"></i>
</button>
<button type="button" class="btn btn-primary ms-1" @click="saveValid">
<i class="bx bx-check"></i>
</button>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup>
import { onMounted, ref, toRaw } from "vue";
import UserList from "@c/user/UserList.vue";
import formInput from "@c/input/FormInput.vue";
import { useToastStore } from "@s/toastStore";
import PlusBtn from "@c/button/PlusBtn.vue";
import DeleteBtn from "@c/button/DeleteBtn.vue";
import $api from "@api";
import router from "@/router";
import { voteCommon } from '@s/voteCommon';
import { useUserStore } from '@s/userList';
import { useRoute } from "vue-router";
const userStore = useUserStore();
const today = new Date().toISOString().substring(0, 10);
const toastStore = useToastStore();
const activeUserList = ref([]);
const disabledUsers = ref([]);
const titleAlert = ref(false);
const endDateAlert = ref(false);
const contentAlerts = ref([false, false]);
const UserListAlert = ref(false);
const title = ref("");
const endDate = ref("");
const { itemList, addItem, removeItem } = voteCommon();
const userListTotal = ref(0);
const addvoteitem = ref(false);
const addvotemulti= ref(false);
const dateInput = ref(null);
const focusDateInput = () => {
if (dateInput.value) {
dateInput.value.showPicker(); // 달력 자동 열기 (일부 브라우저에서 지원)
dateInput.value.focus(); // 포커스 이동
}
};
const userSet = ({ userList, userTotal }) => {
activeUserList.value = userList;
userListTotal.value = userTotal;
};
const handleUserListUpdate = ({ activeUsers, disabledUsers: updatedDisabledUsers }) => {
activeUserList.value = activeUsers;
disabledUsers.value = updatedDisabledUsers;
userListTotal.value = activeUsers.length;
if(activeUserList.value.length<2){
UserListAlert.value = true;
}else{
UserListAlert.value = false;
}
};
const saveValid = () => {
let valid = true;
if (disabledUsers.value.length === 0) {
activeUserList.value = [...userStore.userList];
}
if (title.value.trim() === '') {
titleAlert.value = true;
valid = false;
} else {
titleAlert.value = false;
}
if (endDate.value === '') {
endDateAlert.value = true;
valid = false;
} else {
endDateAlert.value = false;
}
itemList.value.forEach((item, index) => {
if (index < 2 && item.content.trim() === '') {
contentAlerts.value[index] = true;
valid = false;
} else if (index >= 2 && item.content.trim() === '' && item.url.trim() !== '') {
contentAlerts.value[index] = true;
valid = false;
} else {
contentAlerts.value[index] = false;
}
});
if (activeUserList.value.length < 2) {
UserListAlert.value = true;
valid = false;
} else {
UserListAlert.value = false;
}
if (valid) {
saveVote();
}
};
const saveVote = () => {
const filteredItemList = itemList.value.filter(item => item.content && item.content.trim() !== '');
const unwrappedUserList = toRaw(activeUserList.value);
const listId = unwrappedUserList.map(item => ({
id: item.MEMBERSEQ,
}));
$api.post('vote/insertWord',{
addvoteIs :addvoteitem.value === false ? '0' :'1'
,votemMltiIs :addvotemulti.value === false ? '0' : '1'
,title :title.value.trim()
,endDate :endDate.value
,itemList :filteredItemList
,activeUserList :listId
}).then((res)=>{
if(res.data.status == 'OK'){
toastStore.onToast('투표가 등록되었습니다.', 's');
goList();
}
})
};
const ValidHandler = (field) => {
if (field === 'title') {
titleAlert.value = false;
}
if (field.startsWith('content')) {
const index = parseInt(field.replace('content', '')) - 1;
if (!isNaN(index)) {
contentAlerts.value[index] = false;
}
}
};
const ValidHandlerendDate = () =>{
endDateAlert.value = false;
}
const goList = () => {
router.push('/voteboard');
};
</script>
<style scoped>
.item-input {
max-width: 200px;
}
.hidden-date-input {
position: absolute;
top: 28.5%;
left: 17%;
width: 100%;
opacity: 0;
pointer-events: none;
}
</style>