Todo 추가기능 추가 & 모달 팝업을 모바일에서 바텀시트로 수정

This commit is contained in:
yabo0812 2025-10-27 17:37:49 +09:00
parent aa757766cf
commit 0d65be87a2

View File

@ -1129,7 +1129,10 @@
<!-- Todo 단순 조회 (MVP 스코프 축소 v1.5.1) --> <!-- Todo 단순 조회 (MVP 스코프 축소 v1.5.1) -->
<div class="card mb-lg"> <div class="card mb-lg">
<h3 class="card-title">📋 Todo 리스트</h3> <div class="section-header">
<h3 class="card-title">📋 Todo 리스트</h3>
<button class="btn btn-primary btn-sm" onclick="openModal('addTodoModal')">추가</button>
</div>
<p style="font-size: var(--font-small); color: var(--gray-600); margin-bottom: var(--space-md);"> <p style="font-size: var(--font-small); color: var(--gray-600); margin-bottom: var(--space-md);">
Todo 항목은 조회만 가능합니다. 제목, 담당자, 마감일 정보만 표시됩니다. Todo 항목은 조회만 가능합니다. 제목, 담당자, 마감일 정보만 표시됩니다.
</p> </p>
@ -1139,7 +1142,7 @@
<div class="simple-todo-item"> <div class="simple-todo-item">
<div class="simple-todo-header"> <div class="simple-todo-header">
<div class="simple-todo-title">데이터베이스 스키마 설계</div> <div class="simple-todo-title">데이터베이스 스키마 설계</div>
<button class="simple-todo-edit-btn" onclick="editTodo(1)" title="수정">✏️</button> <button class="simple-todo-edit-btn creator-only" onclick="editTodo(1)" title="수정">✏️</button>
</div> </div>
<div class="simple-todo-meta"> <div class="simple-todo-meta">
<span>👤 이준호</span> <span>👤 이준호</span>
@ -1150,7 +1153,7 @@
<div class="simple-todo-item"> <div class="simple-todo-item">
<div class="simple-todo-header"> <div class="simple-todo-header">
<div class="simple-todo-title">API 명세서 작성</div> <div class="simple-todo-title">API 명세서 작성</div>
<button class="simple-todo-edit-btn" onclick="editTodo(2)" title="수정">✏️</button> <button class="simple-todo-edit-btn creator-only" onclick="editTodo(2)" title="수정">✏️</button>
</div> </div>
<div class="simple-todo-meta"> <div class="simple-todo-meta">
<span>👤 이준호</span> <span>👤 이준호</span>
@ -1161,7 +1164,7 @@
<div class="simple-todo-item"> <div class="simple-todo-item">
<div class="simple-todo-header"> <div class="simple-todo-header">
<div class="simple-todo-title">예산 편성안 검토</div> <div class="simple-todo-title">예산 편성안 검토</div>
<button class="simple-todo-edit-btn" onclick="editTodo(3)" title="수정">✏️</button> <button class="simple-todo-edit-btn creator-only" onclick="editTodo(3)" title="수정">✏️</button>
</div> </div>
<div class="simple-todo-meta"> <div class="simple-todo-meta">
<span>👤 김민준</span> <span>👤 김민준</span>
@ -1172,7 +1175,7 @@
<div class="simple-todo-item"> <div class="simple-todo-item">
<div class="simple-todo-header"> <div class="simple-todo-header">
<div class="simple-todo-title">UI 프로토타입 디자인</div> <div class="simple-todo-title">UI 프로토타입 디자인</div>
<button class="simple-todo-edit-btn" onclick="editTodo(4)" title="수정">✏️</button> <button class="simple-todo-edit-btn creator-only" onclick="editTodo(4)" title="수정">✏️</button>
</div> </div>
<div class="simple-todo-meta"> <div class="simple-todo-meta">
<span>👤 최유진</span> <span>👤 최유진</span>
@ -1183,7 +1186,7 @@
<div class="simple-todo-item"> <div class="simple-todo-item">
<div class="simple-todo-header"> <div class="simple-todo-header">
<div class="simple-todo-title">사용자 피드백 분석</div> <div class="simple-todo-title">사용자 피드백 분석</div>
<button class="simple-todo-edit-btn" onclick="editTodo(5)" title="수정">✏️</button> <button class="simple-todo-edit-btn creator-only" onclick="editTodo(5)" title="수정">✏️</button>
</div> </div>
<div class="simple-todo-meta"> <div class="simple-todo-meta">
<span>👤 김민준</span> <span>👤 김민준</span>
@ -1247,17 +1250,27 @@
<div class="modal"> <div class="modal">
<div class="modal-header"> <div class="modal-header">
<h3 class="modal-title">Todo 추가</h3> <h3 class="modal-title">Todo 추가</h3>
<button class="modal-close">×</button> <button class="modal-close" onclick="closeModal('addTodoModal')">×</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
<label class="form-label">Todo 내용</label> <label class="form-label">Todo 내용 <span class="text-error">*</span></label>
<input type="text" class="form-control" placeholder="할 일을 입력하세요"> <input type="text" id="addTodoTitle" class="form-control" placeholder="할 일을 입력하세요">
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label">마감일</label> <label class="form-label">담당자 <span class="text-error">*</span></label>
<select id="addTodoAssignee" class="form-control">
<option value="">담당자를 선택하세요</option>
<option value="김민준">김민준</option>
<option value="이준호">이준호</option>
<option value="박서연">박서연</option>
<option value="최유진">최유진</option>
</select>
</div>
<div class="form-group">
<label class="form-label">마감일 <span class="text-error">*</span></label>
<div class="date-input-wrapper"> <div class="date-input-wrapper">
<input type="date" class="form-control"> <input type="date" id="addTodoDueDate" class="form-control">
</div> </div>
</div> </div>
</div> </div>
@ -1290,22 +1303,12 @@
<option value="박서연">박서연</option> <option value="박서연">박서연</option>
<option value="최유진">최유진</option> <option value="최유진">최유진</option>
</select> </select>
<p class="form-hint">👤 담당자 변경 시 이전/새 담당자에게 알림이 전송됩니다</p>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="form-label">마감일 <span class="text-error">*</span></label> <label class="form-label">마감일 <span class="text-error">*</span></label>
<div class="date-input-wrapper"> <div class="date-input-wrapper">
<input type="date" id="editTodoDueDate" class="form-control"> <input type="date" id="editTodoDueDate" class="form-control">
</div> </div>
<p class="form-hint">📅 마감일 변경 시 캘린더가 자동 업데이트됩니다</p>
</div>
<!-- 권한 안내 (동적 메시지) -->
<div class="alert alert-info" id="editTodoPermissionInfo">
<span class="material-icons" style="font-size: 20px;">info</span>
<div>
<strong>권한 안내</strong>
<p style="margin: 4px 0 0 0; font-size: 14px;" id="editTodoPermissionText">회의 생성자로서 모든 항목을 수정할 수 있습니다.</p>
</div>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -1347,95 +1350,39 @@
z-index: 2; z-index: 2;
} }
/* Todo 편집 모달 - 모바일 전체화면 */ /* Todo 추가/편집 모달 - 바텀시트 스타일 */
#addTodoModal .modal,
#editTodoModal .modal { #editTodoModal .modal {
position: fixed; max-height: 90vh;
top: 0;
left: 0;
right: 0;
bottom: 0;
width: 100%;
height: 100vh;
max-width: none;
max-height: none;
margin: 0;
border-radius: 0;
display: flex;
flex-direction: column;
overflow: hidden;
}
#editTodoModal .modal-header {
flex-shrink: 0;
padding: var(--space-lg) var(--space-md);
border-bottom: 1px solid var(--gray-200);
display: flex;
align-items: center;
justify-content: space-between;
}
#editTodoModal .modal-title {
font-size: var(--font-h3);
font-weight: var(--font-weight-bold);
margin: 0;
}
#editTodoModal .modal-close {
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
font-size: 28px;
background: none;
border: none;
cursor: pointer;
color: var(--gray-600);
border-radius: var(--radius-md);
transition: all var(--transition-fast);
}
#editTodoModal .modal-close:hover {
background: var(--gray-100);
color: var(--gray-900);
}
#editTodoModal .modal-body {
flex: 1;
overflow-y: auto; overflow-y: auto;
padding: var(--space-lg) var(--space-md);
-webkit-overflow-scrolling: touch;
} }
#addTodoModal .modal-footer,
#editTodoModal .modal-footer { #editTodoModal .modal-footer {
flex-shrink: 0;
padding: var(--space-md);
border-top: 1px solid var(--gray-200);
display: flex; display: flex;
gap: var(--space-sm); gap: var(--space-sm);
background: var(--white); justify-content: flex-end;
margin-top: var(--space-md);
} }
#addTodoModal .modal-footer .btn,
#editTodoModal .modal-footer .btn { #editTodoModal .modal-footer .btn {
flex: 1; flex: 1;
} }
/* 데스크톱에서는 중앙 모달로 복원 */ /* 데스크톱에서는 중앙 모달 */
@media (min-width: 768px) { @media (min-width: 768px) {
#addTodoModal .modal,
#editTodoModal .modal { #editTodoModal .modal {
position: relative;
top: auto;
left: auto;
right: auto;
bottom: auto;
width: 90%;
max-width: 600px; max-width: 600px;
height: auto;
max-height: 90vh; max-height: 90vh;
margin: 0 auto;
border-radius: var(--radius-lg);
} }
} }
/* 회의 생성자 전용 요소 숨김 */
.creator-only.hidden {
display: none !important;
}
</style> </style>
<script src="common.js"></script> <script src="common.js"></script>
@ -1766,18 +1713,12 @@
const currentUser = '김민준'; // 현재 로그인 사용자 const currentUser = '김민준'; // 현재 로그인 사용자
const isCreator = checkIfUserIsCreator(CURRENT_MEETING_ID, currentUser); const isCreator = checkIfUserIsCreator(CURRENT_MEETING_ID, currentUser);
// 담당자 필드 표시 여부 결정 // 담당자 필드 표시 여부 결정 (회의 생성자만 표시)
const assigneeGroup = document.getElementById('editTodoAssigneeGroup'); const assigneeGroup = document.getElementById('editTodoAssigneeGroup');
const permissionText = document.getElementById('editTodoPermissionText');
if (isCreator) { if (isCreator) {
// 회의 생성자: 담당자 변경 가능
assigneeGroup.style.display = 'block'; assigneeGroup.style.display = 'block';
permissionText.textContent = '회의 생성자로서 모든 항목을 수정할 수 있습니다.';
} else { } else {
// 일반 담당자: 담당자 변경 불가
assigneeGroup.style.display = 'none'; assigneeGroup.style.display = 'none';
permissionText.textContent = '본인에게 할당된 Todo만 수정할 수 있습니다. 담당자는 변경할 수 없습니다.';
} }
// 모달 열기 // 모달 열기
@ -1852,6 +1793,67 @@
}, 1500); }, 1500);
} }
/**
* Todo 추가 함수
*/
function addTodo() {
const title = document.getElementById('addTodoTitle').value.trim();
const assignee = document.getElementById('addTodoAssignee').value.trim();
const dueDate = document.getElementById('addTodoDueDate').value;
// 유효성 검사
if (!title) {
showToast('Todo 내용을 입력해주세요', 'error');
return;
}
if (!assignee) {
showToast('담당자를 선택해주세요', 'error');
return;
}
if (!dueDate) {
showToast('마감일을 선택해주세요', 'error');
return;
}
// 새 Todo 추가 (실제로는 API 호출)
const newTodo = {
id: 'todo-' + Date.now(),
meetingId: CURRENT_MEETING_ID,
title: title,
assignee: assignee,
dueDate: dueDate,
status: 'pending'
};
meetingTodos.push(newTodo);
showToast('Todo가 추가되었습니다', 'success');
// 담당자에게 알림 전송
setTimeout(() => {
showToast(`${assignee}에게 알림이 전송되었습니다`, 'info');
}, 1000);
// 캘린더 업데이트 알림
setTimeout(() => {
showToast('캘린더가 업데이트되었습니다', 'info');
}, 2000);
closeModal('addTodoModal');
// 입력 필드 초기화
document.getElementById('addTodoTitle').value = '';
document.getElementById('addTodoAssignee').value = '';
document.getElementById('addTodoDueDate').value = '';
// 페이지 새로고침 (실제로는 Todo 리스트만 업데이트)
setTimeout(() => {
location.reload();
}, 2500);
}
/** /**
* 페이지 초기화 * 페이지 초기화
*/ */
@ -1868,6 +1870,12 @@
crownIcon.title = '회의 생성자'; crownIcon.title = '회의 생성자';
// 배지 영역에 크라운 추가 // 배지 영역에 크라운 추가
badgesContainer.appendChild(crownIcon); badgesContainer.appendChild(crownIcon);
} else {
// 회의 생성자가 아닐 경우 creator-only 요소 숨김
const creatorOnlyElements = document.querySelectorAll('.creator-only');
creatorOnlyElements.forEach(element => {
element.classList.add('hidden');
});
} }
updateTodoProgress(); updateTodoProgress();