우선 카드 디테일에서 멤버가 나오지않아 카드 수정시에도 멤버를 불러올수 없었습니다. 그래서 카드 디테일에 멤버가 나오게 아래 코드와 같이 만들었습니다.
// 카드 세부 정보와 코멘트를 가져오는 함수
async function DetailCardGet(columnId, cardId) {
try {
// 카드 세부 정보를 가져오는 API 호출
...
// 카드 세부 정보 응답
const cardData = cardResponse;
const users = [];
for (let i in cardData.members) {
const { boardMembers } = await $.ajax({
type: 'GET',
url: `/boards/${boardId}/members/${cardData.members[i]}`,
beforeSend: function (xhr) {
xhr.setRequestHeader('Content-type', 'application/json');
xhr.setRequestHeader('authorization', `Bearer ${accessToken} `);
},
});
users.push(boardMembers);
}
// 카드에 대한 코멘트를 가져오는 API 호출
...
// 코멘트 응답
const commentsData = commentsResponse;
console.log(commentsResponse);
createCardDetailModal(..., users);
openUpdateCardModal(cardData, columnId, cardId);
} catch (error) {
console.log(error);
}
}
// 카드 세부 정보 모달을 생성하는 함수
function createCardDetailModal(cardData, commentsData, columnId, cardId, users) {
// 모달 바디의 HTML을 생성
// 멤버 리스트의 HTML을 생성
let membersHTML = '';
selectedMembers = [];
selectedMemberNumber = [];
for (const member of users) {
let Img = member[0].profileUrl ? member[0].profileUrl : '/assets/img/favicon.png';
membersHTML += `
<div class="checkbox-group d-flex">
<div class="checkbox-theme-default custom-checkbox checkbox-group__single d-flex">
<img src="${Img}" style="border-radius: 50%; width: 30px; height: 30px; margin-right: 3%;">
<label for="check-grp-${member[0].userId}" class="strikethrough" style="width: 50px;">
${member[0].name}
</label>
</div>
</div>
`;
selectedMembers.push({ name: member[0].name, id: member[0].userId });
console.log('click함', selectedMembers);
selectedMemberNumber.push(member[0].userId);
}
let commentHTML = '';
for (const comment of commentsData) {
// reply_id가 없는 코멘트만 처리
...
}
const modalContentHTML = `
...
<div class="kanban-modal__list">
<ul id="cardDetailMembers">
${membersHTML}
</ul>
</div>
...
`;
// 새로운 모달을 생성
const modal = document.createElement('div');
modal.className = 'modal fade kanban-modal__card kanban__modal';
modal.id = 'exampleModal';
modal.tabIndex = '-1';
modal.setAttribute('aria-labelledby', 'exampleModalLabel');
modal.setAttribute('aria-hidden', 'true');
modal.innerHTML = `
<div class="modal-dialog modal-dialog-scrollable">
<div class="modal-content">
${modalContentHTML}
</div>
</div>
`;
// 모달을 body에 추가
document.body.appendChild(modal);
// 모달을 화면에 표시
$(modal).modal('show');
}
그리고 해당 함수에서 멤버를 뿌려줄때 아래 코드를 추가함으로써 수정 버튼을 클릭했을시 저장된 멤버들이 미리 값으로 들어가있게 해놨습니다.
// 멤버 리스트의 HTML을 생성
let membersHTML = '';
selectedMembers = [];
selectedMemberNumber = [];
for (const member of users) {
...
selectedMembers.push({ name: member[0].name, id: member[0].userId });
console.log('click함', selectedMembers);
selectedMemberNumber.push(member[0].userId);
}
그리고 수정모달에서 멤버를 뿌리고 클릭하기위해 아래 함수를 만들었습니다.
처음에는 select-members라는 아이디 하나로 했었는데 되지않아 따로 만들었습니다.
$(document).ready(() => {
initializeMemberInput('#cardCreateAddMemberBtn', '#cardCreateMemberView', '#selected-members');
initializeMemberInput('#cardUpdateAddMembers', '#cardUpdateMembers', '#update-selected-members');
});
function initializeMemberInput(inputSelector, memberListSelector, selected) {
const memberInput = document.querySelector(inputSelector);
const selectedMemberList = document.querySelector(memberListSelector);
memberInput.addEventListener('click', async (e) => {
clearTimeout(typingTimer);
typingTimer = setTimeout(async () => {
const results = await searchMembers();
console.log(results);
document.getElementById(e.target.id).addEventListener('click', () => {
console.log('id 확인 : ', e.target.id);
});
selectedMemberList.innerHTML = '';
for (let result of results) {
let Img = result.profileUrl ? result.profileUrl : '/assets/img/favicon.png';
let data = `<li>
<a href="#">
<img class="rounded-circle wh-34 bg-opacity-secondary" src="${Img}" alt="${result.name}">
</a>
<span>${result.name}</span>
</li>`;
const li = document.createElement('li');
li.innerHTML = data;
selectedMemberList.appendChild(li);
updateSelectedMembersUI(selected);
li.addEventListener('click', () => {
if (!selectedMemberNumber.includes(result.userId)) {
selectedMembers.push({ name: result.name, id: result.userId });
console.log('click함', selectedMembers);
selectedMemberNumber.push(result.userId);
updateSelectedMembersUI(selected);
}
});
}
});
});
}
// 유저검색
async function searchMembers() {
try {
const { boardMembers } = await $.ajax({
method: 'GET',
url: `/boards/${boardId}/members`,
beforeSend: function (xhr) {
xhr.setRequestHeader('Content-type', 'application/json');
xhr.setRequestHeader('authorization', `Bearer ${accessToken}`);
},
});
return boardMembers;
} catch (err) {
console.error(err);
}
}
// 선택한 멤버 UI 출력
function updateSelectedMembersUI(selected) {
const selectedMemberList = document.querySelector(selected);
selectedMemberList.innerHTML = selectedMembers
.map(
(member) => `
<li>${member.name} <span class="remove-member" data-member="${member.id}">x</span></li>
`
)
.join('');
// 재선택 시 삭제
const removeIcons = selectedMemberList.querySelectorAll('.remove-member');
removeIcons.forEach((icon) => {
icon.addEventListener('click', (e) => {
const memberRemove = e.target.getAttribute('data-member');
selectedMembers = selectedMembers.filter((name) => name.id !== memberRemove);
selectedMemberNumber = selectedMemberNumber.filter((id) => id !== memberRemove);
updateSelectedMembersUI(selected);
});
});
}
기술면접 top30