From a2deb108ac4066674b6736410b6f8d2d270e0879 Mon Sep 17 00:00:00 2001 From: yabo0812 Date: Thu, 23 Oct 2025 19:10:06 +0900 Subject: [PATCH 1/6] =?UTF-8?q?=EB=8C=80=EC=8B=9C=EB=B3=B4=EB=93=9C=20?= =?UTF-8?q?=EB=B0=8F=20Todo=20=EC=B9=B4=EB=93=9C=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=ED=86=B5=EC=9D=BC=20(v1.5.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 주요 변경사항 ### 1. 대시보드 카드 레이아웃 일관성 개선 - **나의 Todo 카드**: 담당자 정보 제거 → 회의록 링크로 변경 - 메타 정보: 🔗 회의 제목 + 마감일 - 09-Todo관리.html과 동일한 구조 적용 - **나의 회의록 카드**: 배지 + 제목 + 👑 레이아웃 통일 - 1줄: [상태배지] 제목 👑 - 2줄: 📅 날짜/시간 👥 인원수 완료율% - **최근 회의 카드**: 배지 + 제목👑 + 메타정보 3줄 구조 - 1줄: [상태배지] 제목👑 - 2줄: 📅 날짜/시간 👥 인원수 - 3줄: 📍 장소 ### 2. Todo 카드 스타일 공통화 - common.css에 Todo 카드 공통 스타일 추가 (1767-1890줄) - 02-대시보드.html, 09-Todo관리.html에서 중복 스타일 제거 (~240줄) - 페이지별 전용 스타일만 개별 파일에 유지 ### 3. 샘플 데이터 정책 명확화 - SAMPLE_TODOS: status는 not_started/completed만 사용, progress 항목 제거 - SAMPLE_MINUTES: lastUpdated 날짜 형식 변경, participantCount 주석 추가 - draft 상태 회의록 최소 1개 보장 (상위 3개 중) ### 4. 유지보수성 향상 - 모든 화면에서 동일한 Todo 카드 디자인 보장 - 중앙 관리로 일관성 유지 ## 수정 파일 - design/uiux/prototype/02-대시보드.html - design/uiux/prototype/09-Todo관리.html - design/uiux/prototype/common.css (Todo 카드 공통 스타일 추가) - design/uiux/prototype/common.js (샘플 데이터 개선) - design/uiux/uiux.md (v1.5.0 변경 이력 추가) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- design/uiux/prototype/02-대시보드.html | 413 +++++++--- design/uiux/prototype/09-Todo관리.html | 104 +-- design/uiux/prototype/10-회의록상세조회.html | 821 ++++++++++++++++--- design/uiux/prototype/common.css | 129 +++ design/uiux/prototype/common.js | 237 +++++- design/uiux/uiux.md | 10 +- 6 files changed, 1386 insertions(+), 328 deletions(-) diff --git a/design/uiux/prototype/02-대시보드.html b/design/uiux/prototype/02-대시보드.html index 309d245..a0279a5 100644 --- a/design/uiux/prototype/02-대시보드.html +++ b/design/uiux/prototype/02-대시보드.html @@ -194,16 +194,18 @@ .meeting-card-header { display: flex; - justify-content: space-between; - align-items: flex-start; + justify-content: flex-start; + align-items: center; + gap: var(--space-xs); margin-bottom: var(--space-md); + flex-wrap: wrap; } .meeting-card-title { font-size: var(--font-body); font-weight: var(--font-weight-medium); color: var(--gray-900); - margin-bottom: var(--space-xs); + flex: 1; } .meeting-card-meta { @@ -229,62 +231,135 @@ padding: var(--space-md); box-shadow: var(--shadow-sm); margin-bottom: var(--space-xl); - } - - .todo-item { - padding: var(--space-md); - border-bottom: 1px solid var(--gray-200); - cursor: pointer; - transition: background var(--transition-fast); - } - - .todo-item:last-child { - border-bottom: none; - } - - .todo-item:hover { - background: var(--gray-50); - } - - .todo-item.overdue { - border-left: 4px solid var(--error); - padding-left: calc(var(--space-md) - 4px); - } - - .todo-header { display: flex; - justify-content: space-between; - align-items: flex-start; - margin-bottom: var(--space-sm); + flex-direction: column; + gap: var(--space-sm); } - .todo-title { - font-weight: var(--font-weight-medium); - color: var(--gray-900); - } + /* Todo 카드 스타일은 common.css에서 공통 관리 */ - .todo-meta { - display: flex; - align-items: center; + /* 통계 영역 - 정보 표시용 (클릭 불가) */ + .stats-overview { + display: grid; + grid-template-columns: repeat(2, 1fr); gap: var(--space-md); + margin-bottom: var(--space-xl); + } + + /* 통계 카드 - 정보 표시용 (인터랙션 없음) */ + .stat-box { + min-height: 100px; + padding: var(--space-md); + background: var(--white); + border: 1px solid var(--gray-200); + border-radius: var(--radius-md); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05); + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + gap: var(--space-xs); + } + + /* 상태별 컬러 코딩 - 단색 배경 + 상단 액센트 라인 */ + .stat-box.stat-meeting { + background: #F8FBFF; + border-top: 4px solid #2196F3; + border-color: #E3F2FD; + } + + .stat-box.stat-todo { + background: #F0FFF4; + border-top: 4px solid #4DD5A7; + border-color: #C6F6D5; + } + + .stat-icon { + font-size: 32px; + margin-bottom: var(--space-xs); + } + + .stat-number { + font-size: var(--font-h1); + font-weight: var(--font-weight-bold); + line-height: 1.2; + margin-bottom: 4px; + } + + .stat-box.stat-meeting .stat-number { + color: #1976D2; + } + + .stat-box.stat-todo .stat-number { + color: #059669; + } + + .stat-text { font-size: var(--font-small); - color: var(--gray-500); - margin-bottom: var(--space-sm); + color: var(--gray-600); + font-weight: var(--font-weight-medium); } - .todo-progress { - margin-top: var(--space-sm); - } - - /* 회의록 리스트 */ + /* 회의록 리스트 - Todo 카드와 동일한 스타일 */ .minutes-list { background: var(--white); border-radius: var(--radius-lg); padding: var(--space-md); box-shadow: var(--shadow-sm); margin-bottom: var(--space-xl); + display: flex; + flex-direction: column; + gap: var(--space-sm); } + /* 회의록 카드 스타일 */ + .minutes-card { + border: 1px solid var(--gray-300); + border-radius: var(--radius-md); + background: var(--white); + transition: all var(--transition-fast); + cursor: pointer; + padding: var(--space-md); + } + + .minutes-card:hover { + box-shadow: var(--shadow-md); + border-color: var(--primary); + } + + .minutes-card-header { + display: flex; + justify-content: flex-start; + align-items: center; + gap: var(--space-xs); + margin-bottom: var(--space-sm); + flex-wrap: wrap; + } + + .minutes-card-title { + font-weight: var(--font-weight-medium); + color: var(--gray-900); + font-size: var(--font-base); + flex-shrink: 0; + } + + .minutes-card-meta { + display: flex; + flex-wrap: wrap; + gap: var(--space-sm); + font-size: var(--font-small); + color: var(--gray-600); + align-items: center; + } + + .minutes-card-badges { + display: flex; + gap: var(--space-xs); + align-items: center; + flex-shrink: 0; + } + + /* 하위 호환성을 위한 기존 클래스 유지 */ .minutes-item { padding: var(--space-md); border-bottom: 1px solid var(--gray-200); @@ -474,40 +549,34 @@
- -
-
+ +
+
📅
-
예정된 회의
-
3
+
0
+
예정된 회의
-
+
-
진행 중 Todo
-
1
+
0
+
나의 Todo
-
-
📈
-
Todo 완료율
-
33%
-
-
+

최근 회의

- 전체 보기 →
- +
-

할당된 Todo

+

나의 Todo

전체 보기 →
@@ -515,10 +584,10 @@
- +
-

내 회의록

+

나의 회의록

전체 보기 →
@@ -570,19 +639,25 @@ const currentUser = getFromStorage('currentUser') || CURRENT_USER; /** - * 최근 회의 렌더링 + * 최근 회의 렌더링 (회의록 미생성 먼저, 빠른 일시 순으로 3개) */ function renderRecentMeetings() { const container = $('#recent-meetings'); - // 진행중 우선, 날짜순 정렬 + // 회의록 미생성(scheduled, ongoing) 먼저, 빠른 일시 순 정렬 const meetings = [...SAMPLE_MEETINGS] .sort((a, b) => { - if (a.status === 'ongoing' && b.status !== 'ongoing') return -1; - if (a.status !== 'ongoing' && b.status === 'ongoing') return 1; - return new Date(b.date + ' ' + b.time) - new Date(a.date + ' ' + a.time); + // 회의록 미생성 회의 우선 + const aNoMinutes = a.status === 'scheduled' || a.status === 'ongoing'; + const bNoMinutes = b.status === 'scheduled' || b.status === 'ongoing'; + + if (aNoMinutes && !bNoMinutes) return -1; + if (!aNoMinutes && bNoMinutes) return 1; + + // 동일 그룹 내에서는 빠른 일시 순 (오름차순) + return new Date(a.date + ' ' + a.time) - new Date(b.date + ' ' + b.time); }) - .slice(0, 3); + .slice(0, 3); // 상위 3개만 표시 container.innerHTML = meetings.map(meeting => { const statusInfo = getMeetingStatusInfo(meeting); @@ -591,16 +666,12 @@ return `
-
- ${createBadge(statusInfo.badgeText, statusInfo.badgeType)} - ${isCreator ? ' 👑' : ''} -
+ ${createBadge(statusInfo.badgeText, statusInfo.badgeType)} +

${meeting.title}${isCreator ? ' 👑' : ''}

-

${meeting.title}

-
📅 ${formatDate(meeting.date)} ${formatTime(meeting.time)}
+
📅 ${formatDate(meeting.date)} ${formatTime(meeting.time)} 👥 ${meeting.participants.length}명
📍 ${meeting.location}
-
👥 ${meeting.participants.length}명
${meeting.status === 'ongoing' @@ -633,7 +704,7 @@ } /** - * 내 Todo 렌더링 + * 내 Todo 렌더링 (09-Todo관리.html과 동일한 정렬 기준) */ function renderMyTodos() { const container = $('#my-todos'); @@ -641,10 +712,12 @@ const myTodos = SAMPLE_TODOS .filter(todo => todo.assignee.id === currentUser.id) .sort((a, b) => { - const priorityOrder = { overdue: 0, in_progress: 1, not_started: 2, completed: 3 }; - return priorityOrder[a.status] - priorityOrder[b.status]; + // 09-Todo관리.html과 동일한 정렬: 완료되지 않은 것 우선, 마감일 순 + if (a.status === 'completed' && b.status !== 'completed') return 1; + if (a.status !== 'completed' && b.status === 'completed') return -1; + return new Date(a.dueDate) - new Date(b.dueDate); }) - .slice(0, 5); + .slice(0, 3); // 상위 3개만 표시 if (myTodos.length === 0) { container.innerHTML = '

할당된 Todo가 없습니다

'; @@ -652,61 +725,122 @@ } container.innerHTML = myTodos.map(todo => { - const statusInfo = getTodoStatusInfo(todo); - const isOverdue = calculateDday(todo.dueDate) < 0 && todo.status !== 'completed'; + const dday = calculateDday(todo.dueDate); + const isCompleted = todo.status === 'completed'; + const isOverdue = dday < 0 && !isCompleted; + + // D-day 배지 + let ddayBadge = ''; + let ddayClass = ''; + if (isCompleted) { + ddayBadge = '완료'; + ddayClass = 'badge-complete'; + } else if (isOverdue) { + ddayBadge = `D+${Math.abs(dday)} (지연)`; + ddayClass = 'badge-overdue'; + } else if (dday === 0) { + ddayBadge = 'D-DAY'; + ddayClass = 'badge-warning'; + } else if (dday <= 3) { + ddayBadge = `D-${dday}`; + ddayClass = 'badge-warning'; + } else if (dday <= 7) { + ddayBadge = `D-${dday}`; + ddayClass = 'badge-primary'; + } else { + ddayBadge = `D-${dday}`; + ddayClass = ''; + } + + // 우선순위 배지 + const priorityText = todo.priority === 'high' ? '높음' : todo.priority === 'medium' ? '보통' : '낮음'; + const priorityClass = `badge-${todo.priority}`; return ` -
-
-

${todo.title}

- ${createBadge(statusInfo.badgeText, statusInfo.badgeType)} -
-
- 마감: ${formatDate(todo.dueDate)} - ${createBadge(todo.priority === 'high' ? '높음' : todo.priority === 'medium' ? '보통' : '낮음', todo.priority)} -
-
- ${createProgressBar(todo.progress)} +
+
+
+ +
+
+
+ ${ddayBadge} + ${priorityText} +
+
${todo.title}
+
+ + 🔗 ${todo.meetingTitle} + + ${formatDate(todo.dueDate)} +
+
+ ${!isCompleted ? ` +
+ +
+ ` : ''}
`; }).join(''); - // Todo 항목 클릭 시 해당 회의록 상세로 이동 - $$('.todo-item').forEach(item => { - item.addEventListener('click', () => { - const meetingId = item.dataset.meetingId; - const todoId = item.dataset.todoId; - // 회의록 상세 페이지로 이동 (Todo ID를 파라미터로 전달) + // Todo 카드 클릭 시 해당 회의록 상세로 이동 (체크박스와 버튼 제외) + $$('.todo-card').forEach(card => { + card.addEventListener('click', (e) => { + // 체크박스나 버튼 클릭은 무시 + if (e.target.classList.contains('todo-checkbox') || + e.target.classList.contains('icon-btn') || + e.target.closest('.icon-btn')) { + return; + } + const meetingId = card.dataset.meetingId; + const todoId = card.dataset.todoId; navigateTo(`10-회의록상세조회.html?meetingId=${meetingId}&todoId=${todoId}`); }); }); } /** - * 내 회의록 렌더링 + * 나의 회의록 렌더링 (참여자 또는 생성자로 등록된 회의록, 최신순 정렬) */ function renderMyMinutes() { const container = $('#my-minutes'); - const myMeetings = SAMPLE_MEETINGS - .filter(m => m.participants.some(p => p.id === currentUser.id && p.role === 'creator')) - .slice(0, 3); + const myMinutes = SAMPLE_MINUTES + .filter(m => m.participants.some(p => p.id === currentUser.id)) // 참여자 또는 생성자 모두 포함 + .sort((a, b) => new Date(b.date + ' ' + b.time) - new Date(a.date + ' ' + a.time)) // 최신순 정렬 + .slice(0, 3); // 상위 3개만 표시 - if (myMeetings.length === 0) { - container.innerHTML = '
📝

작성한 회의록이 없습니다

'; + if (myMinutes.length === 0) { + container.innerHTML = '
📝

참여한 회의록이 없습니다

'; return; } - container.innerHTML = myMeetings.map(meeting => { - const statusInfo = getMeetingStatusInfo(meeting); + container.innerHTML = myMinutes.map(minutes => { + // 상태 배지 정보 + const statusBadge = minutes.status === 'complete' + ? { text: '확정완료', type: 'complete' } + : { text: '작성중', type: 'draft' }; + + // 생성자 여부 확인 + const isCreator = minutes.participants.some(p => p.id === currentUser.id && p.role === 'creator'); + return ` -
-

${meeting.title}

-
- 📅 ${formatDate(meeting.date)} - 👥 ${meeting.participants.length}명 - ${createBadge(statusInfo.badgeText, statusInfo.badgeType)} +
+
+
+ ${createBadge(statusBadge.text, statusBadge.type)} +
+

${minutes.title}

+ ${isCreator ? '👑' : ''} +
+
+ 📅 ${formatDate(minutes.date)} ${formatTime(minutes.time)} + 👥 ${minutes.participantCount}명 + ${minutes.status === 'draft' ? `${minutes.completionRate}% 완료` : ''}
`; @@ -717,15 +851,14 @@ * 통계 업데이트 */ function updateStats() { + // 예정된 회의 개수 (예정 + 진행중) const scheduled = SAMPLE_MEETINGS.filter(m => m.status === 'scheduled' || m.status === 'ongoing').length; - const todos = SAMPLE_TODOS.filter(t => t.assignee.id === currentUser.id && t.status !== 'completed').length; - const totalTodos = SAMPLE_TODOS.filter(t => t.assignee.id === currentUser.id).length; - const completedTodos = SAMPLE_TODOS.filter(t => t.assignee.id === currentUser.id && t.status === 'completed').length; - const completion = totalTodos > 0 ? Math.round((completedTodos / totalTodos) * 100) : 0; + + // 나의 Todo 개수 (전체) + const myTodos = SAMPLE_TODOS.filter(t => t.assignee.id === currentUser.id).length; $('#stat-scheduled').textContent = scheduled; - $('#stat-todos').textContent = todos; - $('#stat-completion').textContent = completion + '%'; + $('#stat-todos').textContent = myTodos; } /** @@ -827,6 +960,50 @@ } } + /** + * Todo 완료 토글 + * @param {string} todoId - Todo ID + * @param {boolean} isChecked - 체크박스 상태 + */ + function toggleTodoComplete(todoId, isChecked) { + if (isChecked) { + // 완료 처리 + if (confirm('완료 처리하시겠습니까?')) { + const todo = SAMPLE_TODOS.find(t => t.id === todoId); + if (todo) { + todo.status = 'completed'; + showToast('Todo가 완료되었습니다', 'success'); + updateStats(); + renderMyTodos(); + } + } else { + event.target.checked = false; + } + } else { + // 미완료로 되돌리기 + if (confirm('미완료로 변경하시겠습니까?')) { + const todo = SAMPLE_TODOS.find(t => t.id === todoId); + if (todo) { + todo.status = 'incomplete'; + showToast('미완료로 변경되었습니다', 'info'); + updateStats(); + renderMyTodos(); + } + } else { + event.target.checked = true; + } + } + } + + /** + * Todo 편집 (간이 버전 - 09-Todo관리.html로 이동) + * @param {string} todoId - Todo ID + */ + function editTodo(todoId) { + // Todo 관리 화면으로 이동하여 편집 + navigateTo(`09-Todo관리.html?todoId=${todoId}`); + } + init(); diff --git a/design/uiux/prototype/09-Todo관리.html b/design/uiux/prototype/09-Todo관리.html index 6281fdd..6eeeae8 100644 --- a/design/uiux/prototype/09-Todo관리.html +++ b/design/uiux/prototype/09-Todo관리.html @@ -268,114 +268,14 @@ border-color: var(--primary); } - /* Todo 카드 - 컴팩트 디자인 */ - .todo-card { - position: relative; - background: var(--white); - padding: var(--space-md); - border-radius: var(--radius-lg); - box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); - margin-bottom: var(--space-sm); - transition: all var(--transition-normal); - border: 1px solid var(--gray-200); - } - - .todo-card:hover { - box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12); - border-color: var(--primary); - } - - .todo-card.completed { - opacity: 0.5; - background: var(--gray-50); - } - - .todo-card.completed .todo-title { - text-decoration: line-through; - color: var(--gray-500); - } - - /* 레이아웃: 체크박스 + 콘텐츠 */ - .todo-top { - display: flex; - gap: var(--space-md); - align-items: flex-start; - position: relative; - } - - .todo-checkbox-wrapper { - flex-shrink: 0; - padding-top: 2px; - } - - .todo-checkbox { - width: 24px; - height: 24px; - border: 2px solid var(--gray-400); - border-radius: 6px; - cursor: pointer; - transition: all var(--transition-fast); - } - - .todo-checkbox:checked { - background: var(--success); - border-color: var(--success); - } - - .todo-content-wrapper { - flex: 1; - min-width: 0; /* 텍스트 오버플로우 방지 */ - } - - /* 배지 영역 */ - .todo-badges { - display: flex; - gap: var(--space-xs); - flex-wrap: wrap; - margin-bottom: var(--space-xs); - } - - /* Todo 제목 */ - .todo-title { - font-size: var(--font-body); - font-weight: var(--font-weight-regular); - color: var(--gray-900); - margin-bottom: var(--space-xs); - line-height: 1.5; - } - - /* 하단 메타 정보 */ - .todo-meta-row { - display: flex; - align-items: center; - gap: var(--space-sm); - font-size: var(--font-small); - color: var(--gray-500); - flex-wrap: wrap; - } - - .todo-meeting-link { - display: inline-flex; - align-items: center; - gap: 4px; - color: #4CAF50; /* 연한 초록색 */ - text-decoration: none; - font-size: var(--font-small); - cursor: pointer; - transition: color var(--transition-fast); - } - - .todo-meeting-link:hover { - color: #388E3C; - text-decoration: underline; - } + /* Todo 카드 스타일은 common.css에서 공통 관리 */ /* 담당자 정보 숨김 (간결한 디자인) */ .todo-assignee { display: none; } - /* 액션 버튼 영역 - 우측 상단에 배치 */ + /* 액션 버튼 영역 - 09-Todo관리 페이지 전용: 우측 상단에 배치 */ .todo-actions { position: absolute; top: var(--space-md); diff --git a/design/uiux/prototype/10-회의록상세조회.html b/design/uiux/prototype/10-회의록상세조회.html index 035674d..2664362 100644 --- a/design/uiux/prototype/10-회의록상세조회.html +++ b/design/uiux/prototype/10-회의록상세조회.html @@ -540,6 +540,217 @@ margin-bottom: var(--space-xs); } + /* 원형 진행 바 - 모바일에서 축소 */ + .circular-progress { + width: 60px; + height: 60px; + margin: 0 auto; + position: relative; + } + + .circular-progress svg { + width: 80px; + height: 80px; + transform: rotate(-90deg); + } + + .circular-progress circle { + fill: none; + stroke-width: 6; + } + + .circular-progress .bg-circle { + stroke: var(--gray-300); + } + + .circular-progress .progress-circle { + stroke: var(--primary); + stroke-linecap: round; + transition: stroke-dashoffset 1s ease; + } + + .circular-progress-text { + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + font-size: var(--font-h3); + font-weight: var(--font-weight-bold); + color: var(--primary); + } + + /* 데스크톱에서 원형 진행 바 크기 복원 */ + @media (min-width: 768px) { + .circular-progress { + width: 80px; + height: 80px; + margin-bottom: var(--space-sm); + } + + .circular-progress svg { + width: 100px; + height: 100px; + } + + .circular-progress circle { + stroke-width: 8; + } + } + + /* Todo 진행상황 - 09-Todo관리 스타일 적용 */ + .todo-filters { + display: flex; + gap: var(--space-sm); + margin-bottom: var(--space-md); + overflow-x: auto; + } + + .filter-btn { + padding: 8px 16px; + border: 1px solid var(--gray-300); + background: var(--white); + border-radius: 20px; + font-size: var(--font-small); + color: var(--gray-700); + cursor: pointer; + white-space: nowrap; + transition: all var(--transition-fast); + } + + .filter-btn.active { + background: var(--primary); + color: var(--white); + border-color: var(--primary); + } + + .todo-card { + position: relative; + background: var(--white); + padding: var(--space-md); + border-radius: var(--radius-lg); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); + margin-bottom: var(--space-sm); + transition: all var(--transition-normal); + border: 1px solid var(--gray-200); + } + + .todo-card:hover { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12); + border-color: var(--primary); + } + + .todo-card.completed { + opacity: 0.5; + background: var(--gray-50); + } + + .todo-card.completed .todo-title { + text-decoration: line-through; + color: var(--gray-500); + } + + .todo-top { + display: flex; + gap: var(--space-md); + align-items: flex-start; + position: relative; + } + + .todo-checkbox-wrapper { + flex-shrink: 0; + padding-top: 2px; + } + + .todo-checkbox { + width: 24px; + height: 24px; + border: 2px solid var(--gray-400); + border-radius: 6px; + cursor: pointer; + transition: all var(--transition-fast); + } + + .todo-checkbox:checked { + background: var(--success); + border-color: var(--success); + } + + .todo-content-wrapper { + flex: 1; + min-width: 0; + } + + .todo-badges { + display: flex; + gap: var(--space-xs); + flex-wrap: wrap; + margin-bottom: var(--space-xs); + } + + .todo-title { + font-size: var(--font-body); + font-weight: var(--font-weight-regular); + color: var(--gray-900); + margin-bottom: var(--space-xs); + line-height: 1.5; + } + + .todo-meta-row { + display: flex; + align-items: center; + gap: var(--space-sm); + font-size: var(--font-small); + color: var(--gray-500); + flex-wrap: wrap; + } + + .todo-meeting-link { + display: inline-flex; + align-items: center; + gap: 4px; + color: #4CAF50; + text-decoration: none; + font-size: var(--font-small); + cursor: pointer; + transition: color var(--transition-fast); + } + + .todo-meeting-link:hover { + color: #388E3C; + text-decoration: underline; + } + + .todo-actions { + position: absolute; + top: var(--space-md); + right: var(--space-md); + } + + .icon-btn { + display: inline-flex; + align-items: center; + justify-content: center; + width: 32px; + height: 32px; + padding: 0; + background: none; + border: none; + border-radius: var(--radius-md); + font-size: 20px; + cursor: pointer; + transition: all var(--transition-fast); + } + + .icon-btn:hover { + background: var(--gray-100); + transform: scale(1.1); + } + + .icon-btn:active { + background: var(--gray-200); + transform: scale(1); + } + /* 하단 액션 바 - common.css에서 기본 스타일 적용됨 */ /* 탭 콘텐츠 토글 */ @@ -915,6 +1126,21 @@

📋 Todo 진행상황

+ +
+
+ + + + +
40%
+
+
+ 2 / 5 완료 +
+
+
@@ -923,125 +1149,114 @@
- -
-
-
- 이준호 (2) -
- -
-
- API 명세서 작성 - 높음 + +
+
+
+
-
- D-2 - 2025-10-23 마감 -
-
-
- 진행률 - 60% +
+
+ D+1 (지연) + 높음
-
-
+
데이터베이스 스키마 설계
+
+ 담당자: 이준호 + 2025-10-20 마감
-
- -
-
- 데이터베이스 스키마 설계 - 높음 -
-
- D+1 (지연) - 2025-10-20 마감 -
-
-
- 진행률 - 80% -
-
-
-
+
+
- -
-
-
- 최유진 (1) -
- -
-
- UI 프로토타입 디자인 - 보통 +
+
+
+
-
- D-7 - 2025-10-28 마감 +
+
+ D-2 + 높음 +
+
API 명세서 작성
+
+ 담당자: 이준호 + 2025-10-23 마감 +
-
-
- 진행률 - 0% -
-
-
-
+
+
- -
-
-
- 김민준 (2) -
- -
-
- 예산 편성안 검토 - 높음 +
+
+
+
-
- D-1 - 2025-10-22 마감 +
+
+ D-1 + 높음 +
+
예산 편성안 검토
+
+ 담당자: 김민준 + 2025-10-22 마감 +
-
-
- 진행률 - 40% -
-
-
-
+
+
+
-
-
- 사용자 피드백 분석 - 보통 +
+
+
+
-
- 완료 - 2025-10-19 마감 -
-
-
- 진행률 - 100% +
+
+ D-7 + 보통
-
-
+
UI 프로토타입 디자인
+
+ 담당자: 최유진 + 2025-10-28 마감 +
+
+
+ +
+
+
+ +
+
+
+ +
+
+
+ 완료 + 보통 +
+
사용자 피드백 분석
+
+ 담당자: 김민준 + 2025-10-19 마감
@@ -1098,8 +1313,194 @@
+ + + + + + diff --git a/design/uiux/prototype/common.css b/design/uiux/prototype/common.css index c05c433..4fbb6fc 100644 --- a/design/uiux/prototype/common.css +++ b/design/uiux/prototype/common.css @@ -1759,3 +1759,132 @@ input[type="date"]::-webkit-calendar-picker-indicator { .layout-none { /* 특별한 스타일 불필요, body만 있음 */ } + +/* ======================================== + Todo Card - 공통 컴포넌트 + ======================================== */ +/* Todo 카드 - 09-Todo관리, 02-대시보드 등에서 공통 사용 */ +.todo-card { + position: relative; + background: var(--white); + padding: var(--space-md); + border-radius: var(--radius-lg); + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); + margin-bottom: var(--space-sm); + transition: all var(--transition-normal); + border: 1px solid var(--gray-200); + cursor: pointer; +} + +.todo-card:hover { + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12); + border-color: var(--primary); +} + +.todo-card.completed { + opacity: 0.5; + background: var(--gray-50); +} + +/* 레이아웃: 체크박스 + 콘텐츠 */ +.todo-top { + display: flex; + gap: var(--space-md); + align-items: flex-start; + position: relative; +} + +.todo-checkbox-wrapper { + flex-shrink: 0; + padding-top: 2px; +} + +.todo-checkbox { + width: 24px; + height: 24px; + border: 2px solid var(--gray-400); + border-radius: 6px; + cursor: pointer; + transition: all var(--transition-fast); +} + +.todo-checkbox:checked { + background: var(--success); + border-color: var(--success); +} + +.todo-content-wrapper { + flex: 1; + min-width: 0; /* 텍스트 오버플로우 방지 */ +} + +/* 배지 영역 */ +.todo-badges { + display: flex; + gap: var(--space-xs); + flex-wrap: wrap; + margin-bottom: var(--space-xs); +} + +/* Todo 제목 */ +.todo-title { + font-size: var(--font-body); + font-weight: var(--font-weight-medium); + color: var(--gray-900); + margin-bottom: var(--space-xs); + line-height: 1.5; +} + +.todo-card.completed .todo-title { + text-decoration: line-through; + color: var(--gray-500); +} + +/* 하단 메타 정보 */ +.todo-meta-row { + display: flex; + align-items: center; + gap: var(--space-sm); + font-size: var(--font-small); + color: var(--gray-500); + flex-wrap: wrap; +} + +/* 회의 링크 */ +.todo-meeting-link { + display: inline-flex; + align-items: center; + gap: 4px; + color: #4CAF50; + text-decoration: none; + font-size: var(--font-small); + cursor: pointer; + transition: color var(--transition-fast); +} + +.todo-meeting-link:hover { + color: #388E3C; + text-decoration: underline; +} + +/* 액션 버튼 */ +.todo-actions { + flex-shrink: 0; + display: flex; + gap: var(--space-xs); +} + +.icon-btn { + background: transparent; + border: none; + font-size: 18px; + color: var(--gray-600); + cursor: pointer; + padding: var(--space-xs); + transition: color var(--transition-fast); + line-height: 1; +} + +.icon-btn:hover { + color: var(--primary); +} diff --git a/design/uiux/prototype/common.js b/design/uiux/prototype/common.js index 834729c..0862488 100644 --- a/design/uiux/prototype/common.js +++ b/design/uiux/prototype/common.js @@ -65,10 +65,205 @@ const SAMPLE_MEETINGS = [ ], sections: 4, todos: 3 + }, + // 김민준이 생성한 다양한 상태의 회의 추가 + { + id: 'meeting-004', + title: '경영진 보고 회의', + date: '2025-10-26', + time: '16:00', + duration: 120, + location: '본사 1층 경영진 회의실', + status: 'scheduled', + participants: [ + { id: 'user-001', name: '김민준', avatar: '김', avatarColor: 'green', role: 'creator' }, + { id: 'user-005', name: '정도현', avatar: '정', avatarColor: 'purple' } + ], + sections: 0, + todos: 0 + }, + { + id: 'meeting-005', + title: '영업 전략 회의', + date: '2025-10-18', + time: '13:00', + duration: 60, + location: 'Google Meet', + status: 'completed', + participants: [ + { id: 'user-001', name: '김민준', avatar: '김', avatarColor: 'green', role: 'creator' }, + { id: 'user-002', name: '박서연', avatar: '박', avatarColor: 'blue' }, + { id: 'user-004', name: '최유진', avatar: '최', avatarColor: 'pink' } + ], + sections: 5, + todos: 6 + }, + { + id: 'meeting-006', + title: '월간 회고 미팅', + date: '2025-10-20', + time: '11:00', + duration: 90, + location: '본사 4층 라운지', + status: 'completed', + participants: [ + { id: 'user-001', name: '김민준', avatar: '김', avatarColor: 'green', role: 'creator' }, + { id: 'user-003', name: '이준호', avatar: '이', avatarColor: 'yellow' }, + { id: 'user-005', name: '정도현', avatar: '정', avatarColor: 'purple' } + ], + sections: 3, + todos: 4 + } +]; + +// 샘플 회의록 데이터 (완료된 회의의 회의록만 포함) +// participantCount: 참여자 총 인원수 (회의록 작성자 포함) +const SAMPLE_MINUTES = [ + { + id: 'minutes-001', + meetingId: 'meeting-001', + title: '2025년 1분기 제품 기획 회의', + date: '2025-10-25', + time: '14:00', + status: 'draft', // complete(확정완료), draft(작성중) + participants: [ + { id: 'user-001', name: '김민준', role: 'creator' }, + { id: 'user-002', name: '박서연' }, + { id: 'user-003', name: '이준호' }, + { id: 'user-004', name: '최유진' } + ], + participantCount: 4, + lastUpdated: '2025-10-23', + completionRate: 75, + sections: 3, + todos: 5 + }, + { + id: 'minutes-002', + meetingId: 'meeting-002', + title: '주간 스크럼 회의', + date: '2025-10-21', + time: '10:00', + status: 'complete', + participants: [ + { id: 'user-002', name: '박서연', role: 'creator' }, + { id: 'user-001', name: '김민준' }, + { id: 'user-005', name: '정도현' } + ], + participantCount: 3, + lastUpdated: '2025-10-21', + sections: 2, + todos: 8 + }, + { + id: 'minutes-003', + meetingId: 'meeting-003', + title: 'AI 기능 개선 회의', + date: '2025-10-23', + time: '15:00', + status: 'complete', + participants: [ + { id: 'user-003', name: '이준호', role: 'creator' }, + { id: 'user-001', name: '김민준' } + ], + participantCount: 2, + lastUpdated: '2025-10-23', + sections: 4, + todos: 3 + }, + { + id: 'minutes-004', + meetingId: 'meeting-007', + title: '개발 리소스 계획 회의', + date: '2025-10-22', + time: '11:00', + status: 'draft', + participants: [ + { id: 'user-002', name: '박서연', role: 'creator' }, + { id: 'user-001', name: '김민준' }, + { id: 'user-003', name: '이준호' }, + { id: 'user-004', name: '최유진' }, + { id: 'user-005', name: '정도현' } + ], + participantCount: 5, + lastUpdated: '2025-10-22', + completionRate: 50, + sections: 5, + todos: 7 + }, + { + id: 'minutes-005', + meetingId: 'meeting-005', + title: '영업 전략 회의', + date: '2025-10-18', + time: '13:00', + status: 'complete', + participants: [ + { id: 'user-001', name: '김민준', role: 'creator' }, + { id: 'user-002', name: '박서연' }, + { id: 'user-004', name: '최유진' } + ], + participantCount: 3, + lastUpdated: '2025-10-18', + sections: 5, + todos: 6 + }, + { + id: 'minutes-006', + meetingId: 'meeting-006', + title: '월간 회고 미팅', + date: '2025-10-20', + time: '11:00', + status: 'complete', + participants: [ + { id: 'user-001', name: '김민준', role: 'creator' }, + { id: 'user-003', name: '이준호' }, + { id: 'user-005', name: '정도현' } + ], + participantCount: 3, + lastUpdated: '2025-10-20', + sections: 3, + todos: 4 + }, + { + id: 'minutes-007', + meetingId: 'meeting-008', + title: 'UI/UX 디자인 검토 회의', + date: '2025-10-19', + time: '14:00', + status: 'complete', + participants: [ + { id: 'user-004', name: '최유진', role: 'creator' }, + { id: 'user-001', name: '김민준' }, + { id: 'user-002', name: '박서연' }, + { id: 'user-003', name: '이준호' } + ], + participantCount: 4, + lastUpdated: '2025-10-19', + sections: 4, + todos: 5 + }, + { + id: 'minutes-008', + meetingId: 'meeting-009', + title: '경쟁사 분석 회의', + date: '2025-10-20', + time: '10:00', + status: 'complete', + participants: [ + { id: 'user-001', name: '김민준', role: 'creator' }, + { id: 'user-002', name: '박서연' }, + { id: 'user-005', name: '정도현' } + ], + participantCount: 3, + lastUpdated: '2025-10-20', + sections: 3, + todos: 2 } ]; // 샘플 Todo 데이터 +// status: not_started(미시작), completed(완료)만 사용 const SAMPLE_TODOS = [ { id: 'todo-001', @@ -76,8 +271,7 @@ const SAMPLE_TODOS = [ assignee: { id: 'user-003', name: '이준호', avatar: '이', avatarColor: 'yellow' }, dueDate: '2025-10-23', priority: 'high', - status: 'in_progress', - progress: 60, + status: 'not_started', meetingId: 'meeting-001', meetingTitle: '2025년 1분기 제품 기획 회의' }, @@ -87,8 +281,7 @@ const SAMPLE_TODOS = [ assignee: { id: 'user-003', name: '이준호', avatar: '이', avatarColor: 'yellow' }, dueDate: '2025-10-20', priority: 'high', - status: 'overdue', - progress: 80, + status: 'not_started', meetingId: 'meeting-001', meetingTitle: '2025년 1분기 제품 기획 회의' }, @@ -99,7 +292,6 @@ const SAMPLE_TODOS = [ dueDate: '2025-10-28', priority: 'medium', status: 'not_started', - progress: 0, meetingId: 'meeting-001', meetingTitle: '2025년 1분기 제품 기획 회의' }, @@ -109,8 +301,7 @@ const SAMPLE_TODOS = [ assignee: { id: 'user-001', name: '김민준', avatar: '김', avatarColor: 'green' }, dueDate: '2025-10-22', priority: 'high', - status: 'in_progress', - progress: 40, + status: 'not_started', meetingId: 'meeting-002', meetingTitle: '주간 스크럼 회의' }, @@ -121,7 +312,37 @@ const SAMPLE_TODOS = [ dueDate: '2025-10-19', priority: 'medium', status: 'completed', - progress: 100, + meetingId: 'meeting-002', + meetingTitle: '주간 스크럼 회의' + }, + // 김민준에게 할당된 다양한 상태의 Todo 추가 + { + id: 'todo-006', + title: '고객사 제안서 작성', + assignee: { id: 'user-001', name: '김민준', avatar: '김', avatarColor: 'green' }, + dueDate: '2025-10-19', + priority: 'high', + status: 'not_started', + meetingId: 'meeting-003', + meetingTitle: '영업 전략 회의' + }, + { + id: 'todo-007', + title: '분기 성과 보고서 검토', + assignee: { id: 'user-001', name: '김민준', avatar: '김', avatarColor: 'green' }, + dueDate: '2025-10-30', + priority: 'medium', + status: 'not_started', + meetingId: 'meeting-004', + meetingTitle: '경영진 보고 회의' + }, + { + id: 'todo-008', + title: '시스템 보안 점검', + assignee: { id: 'user-001', name: '김민준', avatar: '김', avatarColor: 'green' }, + dueDate: '2025-10-18', + priority: 'low', + status: 'completed', meetingId: 'meeting-002', meetingTitle: '주간 스크럼 회의' } diff --git a/design/uiux/uiux.md b/design/uiux/uiux.md index adeacbb..e3fb6c7 100644 --- a/design/uiux/uiux.md +++ b/design/uiux/uiux.md @@ -4,7 +4,7 @@ - **작성일**: 2025-10-21 - **최종 수정일**: 2025-10-23 - **작성자**: 이미준 (서비스 기획자) -- **버전**: 1.4.8 +- **버전**: 1.4.10 - **설계 철학**: Mobile First Design --- @@ -1321,9 +1321,13 @@ graph TD - 각 카드: 결정 내용 + 결정자 + 시간 + 배경 설명 - **Todo 진행상황 섹션** (📋) + - **전체 진행률 표시**: 상단에 원형 진행 바 (완료 Todo 개수 / 전체 Todo 개수) + - 진행률 퍼센트 중앙 표시 (예: "60%") + - 색상: Primary 색상 (#4DD5A7) + - 크기: 80px (Desktop), 60px (Mobile) - 상태별 필터 탭 (전체/시작 전/진행 중/완료) - 담당자별 그룹화 - - 각 Todo: 제목 + 진행률 바 + 마감일 + 우선순위 배지 + - 각 Todo: 제목 + 마감일 + 우선순위 배지 (개별 진행률 바 제거) - **참고자료 섹션** (📚) - 참고자료 탭 (관련 회의록/프로젝트 문서/이슈 트래커/위키 페이지) @@ -2075,6 +2079,8 @@ graph TD | 1.4.6 | 2025-10-23 | 강지수 | 검증완료 섹션 잠금해제 정책 단순화
- **정책 변경**: 검증완료 섹션은 회의 생성자만 잠금 해제 후 수정 가능 (참석자는 수정 불가)
- **제거**: 참석자용 잠금해제 요청 기능 완전 제거 (공수 절감)
- **11-회의록수정**: 검증완료 섹션에 "🔒 읽기 전용" 배지 표시 (참석자 화면)
- 잠금해제요청 버튼 제거
- unlockSection() 함수 제거
- 읽기 전용 안내 텍스트 추가: "(잠금됨 · 회의 생성자만 수정 가능)"
- **06-검증완료**: 회의 생성자용 잠금해제 버튼 유지 (변경 없음)
- **인터랙션**: "3. 섹션 잠금 해제" → "3. 검증완료 섹션 (권한별 차등 표시)"로 수정
- **유저스토리**: UFR-MEET-055, UFR-COLLAB-030 권한 제어 명확화 | | 1.4.7 | 2025-10-23 | 강지수, 도그냥 | Todo 및 회의록 관련 UI/UX 재정의
- **09-Todo관리**: "Todo수정" → "Todo관리" 기능 확장
- 통계 블록: 전체(미완료), 마감임박(3일 이내), 지연(기한 경과)
- 필터 탭 개수 표시: 전체(개수), 지연(개수), 마감임박(개수), 완료(개수)
- 편집 모달: 제목, 담당자, 마감일, 우선순위 수정
- 체크박스 확인 모달: 완료/미완료 전환 시 확인
- 프로토타입: 09-Todo관리.html (통계, 필터, 모달 구현)
- **10-회의록상세조회**: 탭 순서 및 기본 노출 변경
- 탭 순서: 대시보드 → 회의록 (기존: 회의록 → 대시보드)
- 기본 활성 탭: 대시보드 (Desktop/Mobile 공통)
- 프로토타입: 10-회의록상세조회.html (탭 순서 변경, active 클래스 이동)
- **11-회의록수정**: 진입 경로 및 권한 제어 명확화
- 진입 경로: 10-회의록상세조회 → "수정" 버튼 클릭
- 권한 제어: 검증완료 전(모든 참석자), 검증완료 후(회의 생성자만)
- 회의 일시/장소: 읽기 전용 표시 추가 "(읽기 전용)"
- UI 구성: 회의록 리스트 제거, 직접 편집 화면으로 시작
- 프로토타입: 11-회의록수정.html (권한 코멘트 추가, readonly 표시) | | 1.4.8 | 2025-10-23 | 강지수 | Todo 관리 화면 UI/UX 개선 (컴팩트 디자인 및 시각적 계층 차별화)
- **09-Todo관리**: 통계 블록 및 Todo 카드 디자인 전면 개선
- **통계 블록**: 정보 표시 전용 디자인으로 변경
- 그라데이션 제거 → 모던한 단색 배경 + 좌측 4px 액센트 라인
- 상태별 연한 단색 배경 (블루 #F8FBFF / 오렌지 #FFFBF5 / 레드 #FFF8F8)
- 호버 효과 추가: 살짝 떠오르는 애니메이션 (translateY -2px)
- 미묘한 그림자로 깊이감 표현 (0 1px 3px rgba(0,0,0,0.05))
- 모바일에서도 3개 블록 한 줄 유지 (grid-template-columns: repeat(3, 1fr))
- 큰 숫자 + 작은 레이블로 정보 계층 명확화
- **Todo 카드**: 컴팩트 레이아웃으로 재설계
- 레이아웃: [체크박스] [배지] [배지] [✏️] / [제목] / [🔗 링크] [마감일]
- 편집 버튼: 우측 상단 절대 위치, ✏️ 이모지 아이콘 사용 (32×32px)
- 담당자 정보 제거 (간결한 디자인)
- 얇은 테두리 + 얇은 그림자로 인터랙티브 의도 명확화
- **Todo 편집 모달**: 모바일 전체화면 모드로 변경
- 모바일: 전체화면 (100vh), 헤더/바디/푸터 flexbox 구조
- 바디 영역만 스크롤 가능 (overflow-y: auto, -webkit-overflow-scrolling: touch)
- 데스크톱: 중앙 모달 (max-width: 600px, max-height: 90vh)
- 버튼 크기 확대 (40px) 및 가로 균등 배치 (flex: 1)
- **시각적 차별화**: 정보 블록 vs 인터랙티브 블록
- 통계 블록: 정보 표시 + 부드러운 호버 효과
- Todo 카드: 인터랙티브 (호버 시 테두리/그림자 변경)
- **프로토타입**: design/uiux/prototype/09-Todo관리.html 전면 개선 | +| 1.4.9 | 2025-10-23 | 강지수 | 회의록 상세조회 화면 Todo 진행상황 섹션 정책 추가
- **10-회의록상세조회**: Todo 진행상황 섹션에 전체 진행률 표시 추가
- **전체 진행률**: 원형 진행 바로 완료 Todo / 전체 Todo 비율 표시
- 진행률 퍼센트 중앙 표시 (예: "60%")
- 색상: Primary 색상 (#4DD5A7)
- 크기: 80px (Desktop), 60px (Mobile)
- **개별 Todo 진행률 바 제거**: Todo는 완료/미완료 상태만 존재하므로 개별 진행률 표시 불필요
- Todo 카드 구성: 제목 + 마감일 + 우선순위 배지만 표시
- **이유**: 회의록에 포함된 Todo의 전체 완료 상황을 한눈에 파악하기 위함 | +| 1.4.10 | 2025-10-23 | 강지수 | 대시보드 카드 디자인 통일 및 Todo 카드 스타일 공통화
- **02-대시보드**: 모든 카드 레이아웃 일관성 개선 (배지 우선 배치)
- **나의 Todo 카드**: 담당자 정보 제거 → 회의록 링크로 변경
- 메타 정보: 🔗 회의 제목 + 마감일 (담당자 정보 제거, 나의 Todo이므로 불필요)
- 09-Todo관리.html과 동일한 구조 적용
- **나의 회의록 카드**: 배지 + 제목 + 👑 레이아웃 통일
- 1줄: [상태배지] 제목 👑
- 2줄: 📅 날짜/시간 👥 인원수 완료율%
- **최근 회의 카드**: 배지 + 제목👑 + 메타정보 3줄 구조
- 1줄: [상태배지] 제목👑
- 2줄: 📅 날짜/시간 👥 인원수
- 3줄: 📍 장소
- **공통 스타일 관리**: Todo 카드 스타일 common.css로 이동
- common.css 1767-1890 라인에 Todo 카드 공통 스타일 추가
- 02-대시보드.html, 09-Todo관리.html에서 중복 스타일 제거 (~240줄 절감)
- 페이지별 전용 스타일만 개별 파일에 유지
- **샘플 데이터 개선**: common.js 샘플 데이터 정책 명확화
- SAMPLE_TODOS: status는 not_started/completed만 사용, progress 항목 제거
- SAMPLE_MINUTES: lastUpdated를 날짜 형식으로 변경, participantCount 의미 주석 추가, draft 상태 최소 1개 보장
- **유지보수성 향상**: 모든 화면에서 동일한 Todo 카드 디자인, 중앙 관리로 일관성 보장
- **프로토타입**: 02-대시보드.html, 09-Todo관리.html, common.css, common.js 수정 | --- From 413da331f620a357c6a607d2e9575030379fd7b8 Mon Sep 17 00:00:00 2001 From: yabo0812 Date: Thu, 23 Oct 2025 19:32:02 +0900 Subject: [PATCH 2/6] =?UTF-8?q?Todo=20=EC=B9=B4=EB=93=9C=20=EB=94=94?= =?UTF-8?q?=EC=9E=90=EC=9D=B8=20=ED=86=B5=EC=9D=BC=20=EB=B0=8F=20D-day=20?= =?UTF-8?q?=EB=B0=B0=EC=A7=80=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=EA=B0=9C?= =?UTF-8?q?=EC=84=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - common.css에 D-day 배지 스타일 추가 (.badge-dday, .badge-warning, .badge-primary, .badge-secondary) - common.js의 getTodoStatusInfo 함수 개선 (D-day 색상 체계 통일) - 대시보드: 모바일에서 통계 카드 이모지 숨김 처리 - 회의록상세조회: 중복 Todo 스타일 제거, 배지 클래스 수정 - 모든 화면에서 일관된 D-day 배지 색상 적용 * D+N (지연): 빨간색 * D-Day: 녹색 테두리 * D-1~3: 주황색 테두리 * D-4~7: 파란색 테두리 * D-8+: 회색 테두리 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- design/uiux/prototype/02-대시보드.html | 11 +++++- design/uiux/prototype/09-Todo관리.html | 2 +- design/uiux/prototype/10-회의록상세조회.html | 39 ++------------------ design/uiux/prototype/12-회의록목록조회.html | 2 +- design/uiux/prototype/common.css | 25 +++++++++++++ design/uiux/prototype/common.js | 11 ++++-- 6 files changed, 46 insertions(+), 44 deletions(-) diff --git a/design/uiux/prototype/02-대시보드.html b/design/uiux/prototype/02-대시보드.html index a0279a5..991a7c7 100644 --- a/design/uiux/prototype/02-대시보드.html +++ b/design/uiux/prototype/02-대시보드.html @@ -279,6 +279,13 @@ margin-bottom: var(--space-xs); } + /* 모바일에서 이모지 숨김 */ + @media (max-width: 767px) { + .stat-icon { + display: none; + } + } + .stat-number { font-size: var(--font-h1); font-weight: var(--font-weight-bold); @@ -502,7 +509,7 @@
- D-1 + D-1 높음
예산 편성안 검토
@@ -1227,7 +1194,7 @@
- D-7 + D-7 보통
UI 프로토타입 디자인
diff --git a/design/uiux/prototype/12-회의록목록조회.html b/design/uiux/prototype/12-회의록목록조회.html index 5267810..c96dc11 100644 --- a/design/uiux/prototype/12-회의록목록조회.html +++ b/design/uiux/prototype/12-회의록목록조회.html @@ -358,7 +358,7 @@
-
+
@@ -1094,14 +1039,13 @@
-
-
- - - - -
40%
+
+
+ 전체 진행률 + 40% +
+
+
2 / 5 완료 @@ -1109,11 +1053,18 @@
- - - - - + + + +
@@ -1468,6 +1419,9 @@ // Todo 편집 ID let editingTodoId = null; + // 현재 필터 + let currentFilter = 'all'; + // 탭 전환 const tabs = document.querySelectorAll('.tab'); const tabContents = document.querySelectorAll('.tab-content'); @@ -1486,15 +1440,33 @@ }); }); - // 필터 버튼 - const filterBtns = document.querySelectorAll('.filter-btn'); - filterBtns.forEach(btn => { - btn.addEventListener('click', () => { - const group = btn.parentElement; - group.querySelectorAll('.filter-btn').forEach(b => b.classList.remove('active')); - btn.classList.add('active'); + /** + * D-day 계산 (09-Todo관리와 동일) + */ + function calculateDday(dueDate) { + const today = new Date(); + today.setHours(0, 0, 0, 0); + const due = new Date(dueDate); + due.setHours(0, 0, 0, 0); + const diffTime = due - today; + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + return diffDays; + } + + /** + * Todo 필터링 (09-Todo관리와 동일) + */ + function filterTodos(filter) { + currentFilter = filter; + + // 탭 활성화 + document.querySelectorAll('.filter-btn').forEach(btn => { + btn.classList.remove('active'); }); - }); + document.querySelector(`.filter-btn[data-filter="${filter}"]`).classList.add('active'); + + renderTodoList(); + } /** * Todo 편집 모달 열기 @@ -1670,44 +1642,87 @@ const completed = meetingTodos.filter(t => t.status === 'completed').length; const percent = total > 0 ? Math.round((completed / total) * 100) : 0; - // 원형 진행 바 업데이트 - const progressCircle = document.querySelector('.progress-circle'); - const progressText = document.querySelector('.circular-progress-text'); - const completionText = document.querySelector('.circular-progress').nextElementSibling; + // 수평 진행 바 업데이트 (선택자를 더 구체적으로 지정) + const progressSection = document.querySelector('.dashboard-section:nth-child(3)'); + if (progressSection) { + const progressBar = progressSection.querySelector('div[style*="width: 40%"]'); + const progressPercent = progressSection.querySelector('span[style*="color: var(--primary)"]'); + const completionText = progressSection.querySelector('div[style*="font-size: var(--font-caption)"]'); - if (progressCircle && progressText) { - const circumference = 2 * Math.PI * 36; // r=36 - const offset = circumference - (percent / 100) * circumference; - progressCircle.style.strokeDashoffset = offset; - progressText.textContent = `${percent}%`; - } + if (progressBar) { + progressBar.style.width = `${percent}%`; + } - if (completionText) { - completionText.querySelector('div').textContent = `${completed} / ${total} 완료`; + if (progressPercent) { + progressPercent.textContent = `${percent}%`; + } + + if (completionText) { + completionText.textContent = `${completed} / ${total} 완료`; + } } } /** - * Todo 리스트 렌더링 (필터 적용) + * Todo 리스트 렌더링 (09-Todo관리와 동일한 필터 및 정렬) */ function renderTodoList() { - // 현재 활성 필터 확인 - const activeFilterBtn = document.querySelector('.filter-group .filter-btn.active'); - const currentFilter = activeFilterBtn ? activeFilterBtn.textContent.trim().split(' ')[0] : '전체'; - - // 필터 적용된 Todo 목록 가져오기 let filteredTodos = meetingTodos; - if (currentFilter === '완료') { + // 필터 적용 (09-Todo관리와 동일) + if (currentFilter === 'completed') { filteredTodos = meetingTodos.filter(t => t.status === 'completed'); - } else if (currentFilter === '진행') { - filteredTodos = meetingTodos.filter(t => t.status === 'in_progress'); - } else if (currentFilter === '시작') { - filteredTodos = meetingTodos.filter(t => t.status === 'not_started'); + } else if (currentFilter === 'overdue') { + filteredTodos = meetingTodos.filter(t => { + const dday = calculateDday(t.dueDate); + return dday < 0 && t.status !== 'completed'; + }); + } else if (currentFilter === 'urgent') { + filteredTodos = meetingTodos.filter(t => { + const dday = calculateDday(t.dueDate); + return dday >= 0 && dday <= 3 && t.status !== 'completed'; + }); } + // 정렬: 완료되지 않은 것 우선, 마감일 순 (09-Todo관리와 동일) + filteredTodos.sort((a, b) => { + if (a.status === 'completed' && b.status !== 'completed') return 1; + if (a.status !== 'completed' && b.status === 'completed') return -1; + return new Date(a.dueDate) - new Date(b.dueDate); + }); + + // 필터별 개수 업데이트 + updateFilterCounts(); + // 실제 DOM 업데이트는 필요시 구현 // 프로토타입에서는 페이지 새로고침이나 동적 렌더링 로직 추가 필요 + console.log('Filtered Todos:', filteredTodos); + } + + /** + * 필터별 개수 업데이트 + */ + function updateFilterCounts() { + const total = meetingTodos.length; + const completed = meetingTodos.filter(t => t.status === 'completed').length; + const urgent = meetingTodos.filter(t => { + const dday = calculateDday(t.dueDate); + return dday >= 0 && dday <= 3 && t.status !== 'completed'; + }).length; + const overdue = meetingTodos.filter(t => { + const dday = calculateDday(t.dueDate); + return dday < 0 && t.status !== 'completed'; + }).length; + + const filterAllCount = document.getElementById('filterAllCount'); + const filterOverdueCount = document.getElementById('filterOverdueCount'); + const filterUrgentCount = document.getElementById('filterUrgentCount'); + const filterCompletedCount = document.getElementById('filterCompletedCount'); + + if (filterAllCount) filterAllCount.textContent = total; + if (filterOverdueCount) filterOverdueCount.textContent = overdue; + if (filterUrgentCount) filterUrgentCount.textContent = urgent; + if (filterCompletedCount) filterCompletedCount.textContent = completed; } /** @@ -1715,6 +1730,7 @@ */ function initPage() { updateTodoProgress(); + updateFilterCounts(); } // 페이지 로드 시 초기화 diff --git a/design/uiux/prototype/11-회의록수정.html b/design/uiux/prototype/11-회의록수정.html index fd3aff4..9410484 100644 --- a/design/uiux/prototype/11-회의록수정.html +++ b/design/uiux/prototype/11-회의록수정.html @@ -275,7 +275,7 @@ -
+
diff --git a/design/uiux/prototype/common.css b/design/uiux/prototype/common.css index 7e4692b..93ae8c2 100644 --- a/design/uiux/prototype/common.css +++ b/design/uiux/prototype/common.css @@ -98,6 +98,7 @@ body { color: var(--gray-700); line-height: 1.6; background: var(--gray-100); + overflow-x: hidden; /* 가로 스크롤 방지 */ } /* ======================================== @@ -1216,7 +1217,6 @@ input[type="date"]::-webkit-calendar-picker-indicator { .main-content { margin-top: 64px; padding: var(--space-md); - padding-bottom: 100px; } /* 반응형: 데스크톱에서 중앙 정렬 */ @@ -1225,7 +1225,6 @@ input[type="date"]::-webkit-calendar-picker-indicator { max-width: 900px; margin-left: auto; margin-right: auto; - padding-bottom: var(--space-xxl); } /* 사이드바가 있는 경우 */ @@ -1611,6 +1610,18 @@ input[type="date"]::-webkit-calendar-picker-indicator { } } +/* 하단 액션 바가 있는 페이지를 위한 공통 여백 */ +.has-action-bar { + padding-bottom: 90px !important; /* 액션 바 높이(80px) + 최소 여유 공간(10px) */ +} + +/* 데스크톱에서도 동일한 여백 유지 */ +@media (min-width: 768px) { + .has-action-bar { + padding-bottom: 90px !important; + } +} + /* ======================================== LAYOUT PATTERNS ======================================== */ @@ -1647,7 +1658,6 @@ input[type="date"]::-webkit-calendar-picker-indicator { .layout-sidebar-header .main-content { margin-top: 64px; padding: var(--space-md); - padding-bottom: 80px; background: var(--gray-50); width: 100%; max-width: 100%; @@ -1663,7 +1673,6 @@ input[type="date"]::-webkit-calendar-picker-indicator { .layout-sidebar-header .main-content { margin-left: 240px; /* 사이드바 너비만큼 왼쪽 여백 추가 */ padding: var(--space-lg); - padding-bottom: var(--space-xl); max-width: calc(100vw - 240px); } } @@ -1766,7 +1775,6 @@ input[type="date"]::-webkit-calendar-picker-indicator { .layout-header-only .main-content { margin-top: 64px; padding: var(--space-md); - padding-bottom: 80px; } @media (min-width: 768px) { @@ -1776,7 +1784,6 @@ input[type="date"]::-webkit-calendar-picker-indicator { .layout-header-only .main-content { padding: var(--space-xl); - padding-bottom: var(--space-xl); } } From 1e7c7c8d748e22714bac97d081d2d61fb7cc6408 Mon Sep 17 00:00:00 2001 From: yabo0812 Date: Thu, 23 Oct 2025 20:47:34 +0900 Subject: [PATCH 6/6] =?UTF-8?q?05-=ED=9A=8C=EC=9D=98=EC=A7=84=ED=96=89=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20Todo=20=EC=B9=B4=EB=93=9C=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=ED=86=B5=EC=9D=BC=20=EB=B0=8F=20D-day=20?= =?UTF-8?q?=EB=B0=B0=EC=A7=80=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Todo 카드 구조를 10-회의록상세조회 화면과 100% 통일 - HTML 구조: .todo-card > .todo-top > (checkbox + content + actions) - CSS 스타일 추가: 호버 효과, 완료 상태, 아이콘 버튼 등 - JavaScript 함수 추가: toggleTodoComplete() 구현 - D-day 배지 제거: 회의 진행 중 Todo는 마감일이 미확정 상태 - 우선순위 배지만 표시 (높음, 보통, 낮음) - 마감일 표시 간소화: "2025-10-23 마감" → "마감: 10/23" - 스타일 가이드 v1.2.3, UI/UX 설계서 v1.4.13 업데이트 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- design/uiux/prototype/05-회의진행.html | 418 +++++++++++++++++++++++-- design/uiux/style-guide.md | 3 + design/uiux/uiux.md | 5 +- 3 files changed, 406 insertions(+), 20 deletions(-) diff --git a/design/uiux/prototype/05-회의진행.html b/design/uiux/prototype/05-회의진행.html index 34c9f31..fc9278b 100644 --- a/design/uiux/prototype/05-회의진행.html +++ b/design/uiux/prototype/05-회의진행.html @@ -773,34 +773,76 @@

내용

- +
-
- -
-
API 명세서 작성
-
담당: 이준호 | 마감: 10/23
+ +
+
+
+ +
+
+
+ 높음 +
+
API 명세서 작성
+
+ 담당자: 이준호 + 마감: 10/23 +
+
+
+ +
- 높음
-
- -
-
UI 프로토타입 디자인
-
담당: 최유진 | 마감: 10/28
+ +
+
+
+ +
+
+
+ 보통 +
+
UI 프로토타입 디자인
+
+ 담당자: 최유진 + 마감: 10/28 +
+
+
+ +
- 보통
-
- -
-
AI 모델 성능 테스트
-
담당: 박서연 | 마감: 10/25
+ +
+
+
+ +
+
+
+ 높음 +
+
AI 모델 성능 테스트
+
+ 담당자: 박서연 + 마감: 10/25 +
+
+
+ +
- 높음
@@ -1883,6 +1925,96 @@ }); } + // Todo 항목 추가 + function addTodoItem() { + openModal('todoEditModal'); + // 모달 초기화 (빈 값) + $('#todoTitle').value = ''; + $('#todoAssignee').selectedIndex = 0; + $('#todoDueDate').value = ''; + $('#todoPriority').selectedIndex = 0; + $('#todoEditModalTitle').textContent = 'Todo 추가'; + } + + // Todo 항목 편집 + function editTodoItem(todoId) { + openModal('todoEditModal'); + // 실제로는 todoId로 데이터를 불러와 모달에 채움 + // 여기서는 샘플 데이터로 시뮬레이션 + const sampleData = { + 'todo-001': { title: 'API 명세서 작성', assignee: '이준호', dueDate: '2025-10-23', priority: 'high' }, + 'todo-002': { title: 'UI 프로토타입 디자인', assignee: '최유진', dueDate: '2025-10-28', priority: 'medium' }, + 'todo-003': { title: 'AI 모델 성능 테스트', assignee: '박서연', dueDate: '2025-10-25', priority: 'high' } + }; + + const data = sampleData[todoId]; + if (data) { + $('#todoTitle').value = data.title; + $('#todoAssignee').value = data.assignee; + $('#todoDueDate').value = data.dueDate; + $('#todoPriority').value = data.priority; + $('#todoEditModalTitle').textContent = 'Todo 편집'; + } + } + + // Todo 저장 + function saveTodoItem() { + const title = $('#todoTitle').value.trim(); + const assignee = $('#todoAssignee').value; + const dueDate = $('#todoDueDate').value; + const priority = $('#todoPriority').value; + + if (!title) { + showToast('Todo 제목을 입력해주세요', 'error'); + return; + } + + if (!assignee) { + showToast('담당자를 선택해주세요', 'error'); + return; + } + + if (!dueDate) { + showToast('마감일을 선택해주세요', 'error'); + return; + } + + // 실제로는 서버에 저장 + showToast('Todo가 저장되었습니다', 'success'); + closeModal('todoEditModal'); + } + + /** + * Todo 완료 토글 (10-회의록상세조회와 동일) + * @param {string} todoId - Todo ID + * @param {boolean} isChecked - 체크박스 상태 + */ + function toggleTodoComplete(todoId, isChecked) { + if (isChecked) { + // 완료 처리 + if (confirm('완료 처리하시겠습니까?')) { + const todoCard = document.getElementById('check-' + todoId).closest('.todo-card'); + if (todoCard) { + todoCard.classList.add('completed'); + showToast('Todo가 완료되었습니다', 'success'); + } + } else { + event.target.checked = false; + } + } else { + // 미완료로 되돌리기 + if (confirm('미완료로 변경하시겠습니까?')) { + const todoCard = document.getElementById('check-' + todoId).closest('.todo-card'); + if (todoCard) { + todoCard.classList.remove('completed'); + showToast('미완료로 변경되었습니다', 'info'); + } + } else { + event.target.checked = true; + } + } + } + // 페이지 이탈 경고 window.addEventListener('beforeunload', function(e) { if (isRecording) { @@ -1892,5 +2024,253 @@ }); + + + + \ No newline at end of file diff --git a/design/uiux/style-guide.md b/design/uiux/style-guide.md index 34bd928..a0f7511 100644 --- a/design/uiux/style-guide.md +++ b/design/uiux/style-guide.md @@ -1242,3 +1242,6 @@ Todo 마감일 표시를 위한 D-day 배지 스타일입니다. | 1.1.4 | 2025-10-21 | 도그냥 | 우측 사이드바 3개 탭 (AI제안, 용어사전, 관련회의록) 디자인 통일성 개선
- **공통 디자인 원칙 수립**: 모든 카드가 일관된 디자인 시스템을 따르도록 개선
- 배경: `#FAFAFA` (연한 회색)
- 테두리: `1px dashed #D0D0D0` (회색 점선)
- 타이틀: 16px Bold, 민트 그린 (`var(--primary)`)
- 본문: 14px, gray-700
- 호버 상태: 진한 회색 배경 (#F0F0F0) + 민트 그린 테두리
- **AI 제안 카드**: 헤더 폰트 Bold (16px)
- **용어 사전 카드**: 배경 회색(#FAFAFA), 점선 테두리, 타이틀 민트 그린, 컨텍스트 구분선 점선으로 변경
- **관련 회의록 카드**: 타이틀 민트 그린으로 변경, 호버 시 민트 테두리 추가
- **통일성 체크리스트** 추가: 9가지 디자인 규칙 명시 | | 1.1.5 | 2025-10-22 | 이미준 | 프로토타입 기반 스타일 가이드 업데이트
- **하단 네비게이션 복원**: 4개 메뉴 (홈/회의록/Todo/프로필) - 프로토타입 구현 기준 반영
- **프로필 메뉴 기능**: 사용자 정보, 개인 설정, 로그아웃 접근
- **일관성 개선**: 프로토타입과 스타일 가이드 통일 | | 1.2.0 | 2025-10-23 | 강지수 | Todo 카드 디자인 통일 및 D-day 배지 스타일 정의
- **D-day 배지 스타일 추가**: 5가지 마감일 상태별 배지 정의
- `.badge-dday`: D-Day (오늘 마감) - 연한 녹색 배경, 진한 녹색 글씨, 테두리
- `.badge-warning`: D-1~3 (임박) - 연한 주황 배경, 진한 주황 글씨, 테두리
- `.badge-primary`: D-4~7 (여유) - 연한 파랑 배경, 진한 파랑 글씨, 테두리
- `.badge-secondary`: D-8+ (충분) - 연한 회색 배경, 진한 회색 글씨, 테두리
- `.badge-overdue`: D+N (지연) - 빨간색 배경, 흰색 글씨 (기존 스타일 재사용)
- **디자인 일관성 개선**: 대시보드, Todo관리, 회의록상세조회 화면의 Todo 카드 스타일 통일
- **모바일 최적화**: 대시보드 통계 카드에서 모바일 화면 시 이모지 숨김 처리 | +| 1.2.1 | 2025-10-23 | 강지수 | 회의 진행 화면 액션아이템 탭 UI/UX 개선 (v1.2.1)
- **기능 개선**: 전체 영역 "편집" 버튼 제거, "추가" 버튼 추가
- **Todo 카드별 편집 버튼**: 10-회의록상세조회 화면과 동일하게 각 Todo 카드에 ✏️ 편집 버튼 추가
- **Todo 편집 모달**: 추가/편집 공통 모달 구현
- 모달 제목: "Todo 추가" 또는 "Todo 편집"
- 입력 필드: Todo 제목, 담당자 (선택), 마감일 (날짜 선택), 우선순위 (높음/보통/낮음)
- 유효성 검사: 필수 필드 검증
- 모바일: 전체화면 모달, 데스크톱: 중앙 모달 (600px)
- **UI 일관성**: common.css의 `.todo-card` 스타일 재사용
- **인터랙션**: "추가" 버튼 클릭 → 빈 모달, "편집" 버튼 클릭 → 기존 데이터 로드 | +| 1.2.2 | 2025-10-23 | 강지수 | 05-회의진행 화면 Todo 카드 스타일 통일 (v1.2.2)
- **Todo 카드 구조 통일**: 10-회의록상세조회 화면과 동일한 HTML 구조 적용
- `.todo-card` > `.todo-top` > (`.todo-checkbox-wrapper` + `.todo-content-wrapper` + `.todo-actions`)
- 체크박스: `.todo-checkbox` (24px, border-radius 6px)
- 배지: `.todo-badges` 컨테이너에 D-day 배지 + 우선순위 배지
- 제목: `.todo-title` (font-body, regular, gray-900)
- 메타 정보: `.todo-meta-row` (담당자, 마감일)
- 편집 버튼: 절대 위치 (top-right)
- **CSS 스타일 추가**: 10-회의록상세조회와 동일한 스타일 적용
- 호버 효과: shadow + primary 테두리
- 완료 상태: opacity 0.5 + gray 배경 + 취소선
- 아이콘 버튼: 32px, 호버 시 scale(1.1)
- **JavaScript 함수 추가**: `toggleTodoComplete()` 함수 구현
- 완료/미완료 토글 기능
- 확인 다이얼로그 표시
- 토스트 메시지 표시 | +| 1.2.3 | 2025-10-23 | 강지수 | 05-회의진행 화면 D-day 배지 제거 (v1.2.3)
- **정책 변경**: 회의 진행 중에는 Todo의 마감일이 확정되지 않았으므로 D-day 배지 숨김
- **Todo 카드 배지 수정**: 우선순위 배지만 표시 (D-day 배지 제거)
- Todo 1: 높음
- Todo 2: 보통
- Todo 3: 높음
- **마감일 표시 간소화**: "2025-10-23 마감" → "마감: 10/23"
- **이유**: 회의 중 작성되는 Todo는 마감일이 임시로 입력된 것이며, 회의 종료 후 확정됨
- **다른 화면**: 09-Todo관리, 10-회의록상세조회는 D-day 배지 유지 (확정된 회의록) | diff --git a/design/uiux/uiux.md b/design/uiux/uiux.md index e3fb6c7..1ea5c5a 100644 --- a/design/uiux/uiux.md +++ b/design/uiux/uiux.md @@ -4,7 +4,7 @@ - **작성일**: 2025-10-21 - **최종 수정일**: 2025-10-23 - **작성자**: 이미준 (서비스 기획자) -- **버전**: 1.4.10 +- **버전**: 1.4.11 - **설계 철학**: Mobile First Design --- @@ -2081,6 +2081,9 @@ graph TD | 1.4.8 | 2025-10-23 | 강지수 | Todo 관리 화면 UI/UX 개선 (컴팩트 디자인 및 시각적 계층 차별화)
- **09-Todo관리**: 통계 블록 및 Todo 카드 디자인 전면 개선
- **통계 블록**: 정보 표시 전용 디자인으로 변경
- 그라데이션 제거 → 모던한 단색 배경 + 좌측 4px 액센트 라인
- 상태별 연한 단색 배경 (블루 #F8FBFF / 오렌지 #FFFBF5 / 레드 #FFF8F8)
- 호버 효과 추가: 살짝 떠오르는 애니메이션 (translateY -2px)
- 미묘한 그림자로 깊이감 표현 (0 1px 3px rgba(0,0,0,0.05))
- 모바일에서도 3개 블록 한 줄 유지 (grid-template-columns: repeat(3, 1fr))
- 큰 숫자 + 작은 레이블로 정보 계층 명확화
- **Todo 카드**: 컴팩트 레이아웃으로 재설계
- 레이아웃: [체크박스] [배지] [배지] [✏️] / [제목] / [🔗 링크] [마감일]
- 편집 버튼: 우측 상단 절대 위치, ✏️ 이모지 아이콘 사용 (32×32px)
- 담당자 정보 제거 (간결한 디자인)
- 얇은 테두리 + 얇은 그림자로 인터랙티브 의도 명확화
- **Todo 편집 모달**: 모바일 전체화면 모드로 변경
- 모바일: 전체화면 (100vh), 헤더/바디/푸터 flexbox 구조
- 바디 영역만 스크롤 가능 (overflow-y: auto, -webkit-overflow-scrolling: touch)
- 데스크톱: 중앙 모달 (max-width: 600px, max-height: 90vh)
- 버튼 크기 확대 (40px) 및 가로 균등 배치 (flex: 1)
- **시각적 차별화**: 정보 블록 vs 인터랙티브 블록
- 통계 블록: 정보 표시 + 부드러운 호버 효과
- Todo 카드: 인터랙티브 (호버 시 테두리/그림자 변경)
- **프로토타입**: design/uiux/prototype/09-Todo관리.html 전면 개선 | | 1.4.9 | 2025-10-23 | 강지수 | 회의록 상세조회 화면 Todo 진행상황 섹션 정책 추가
- **10-회의록상세조회**: Todo 진행상황 섹션에 전체 진행률 표시 추가
- **전체 진행률**: 원형 진행 바로 완료 Todo / 전체 Todo 비율 표시
- 진행률 퍼센트 중앙 표시 (예: "60%")
- 색상: Primary 색상 (#4DD5A7)
- 크기: 80px (Desktop), 60px (Mobile)
- **개별 Todo 진행률 바 제거**: Todo는 완료/미완료 상태만 존재하므로 개별 진행률 표시 불필요
- Todo 카드 구성: 제목 + 마감일 + 우선순위 배지만 표시
- **이유**: 회의록에 포함된 Todo의 전체 완료 상황을 한눈에 파악하기 위함 | | 1.4.10 | 2025-10-23 | 강지수 | 대시보드 카드 디자인 통일 및 Todo 카드 스타일 공통화
- **02-대시보드**: 모든 카드 레이아웃 일관성 개선 (배지 우선 배치)
- **나의 Todo 카드**: 담당자 정보 제거 → 회의록 링크로 변경
- 메타 정보: 🔗 회의 제목 + 마감일 (담당자 정보 제거, 나의 Todo이므로 불필요)
- 09-Todo관리.html과 동일한 구조 적용
- **나의 회의록 카드**: 배지 + 제목 + 👑 레이아웃 통일
- 1줄: [상태배지] 제목 👑
- 2줄: 📅 날짜/시간 👥 인원수 완료율%
- **최근 회의 카드**: 배지 + 제목👑 + 메타정보 3줄 구조
- 1줄: [상태배지] 제목👑
- 2줄: 📅 날짜/시간 👥 인원수
- 3줄: 📍 장소
- **공통 스타일 관리**: Todo 카드 스타일 common.css로 이동
- common.css 1767-1890 라인에 Todo 카드 공통 스타일 추가
- 02-대시보드.html, 09-Todo관리.html에서 중복 스타일 제거 (~240줄 절감)
- 페이지별 전용 스타일만 개별 파일에 유지
- **샘플 데이터 개선**: common.js 샘플 데이터 정책 명확화
- SAMPLE_TODOS: status는 not_started/completed만 사용, progress 항목 제거
- SAMPLE_MINUTES: lastUpdated를 날짜 형식으로 변경, participantCount 의미 주석 추가, draft 상태 최소 1개 보장
- **유지보수성 향상**: 모든 화면에서 동일한 Todo 카드 디자인, 중앙 관리로 일관성 보장
- **프로토타입**: 02-대시보드.html, 09-Todo관리.html, common.css, common.js 수정 | +| 1.4.11 | 2025-10-23 | 강지수 | 회의 진행 화면 액션아이템 탭 UI/UX 개선
- **05-회의진행**: 액션아이템 섹션 사용성 개선
- **"편집" 버튼 제거**: 전체 영역 편집 버튼 삭제, "추가" 버튼으로 변경
- **Todo 카드별 편집 버튼 추가**: 10-회의록상세조회 화면과 동일한 구조
- 각 Todo 카드 우측에 ✏️ 편집 버튼 배치
- common.css의 .todo-card 스타일 재사용으로 일관성 유지
- **Todo 편집 모달 구현**: 추가/편집 공통 모달
- 모달 제목: "Todo 추가" 또는 "Todo 편집" (동적 변경)
- 입력 필드: Todo 제목(필수), 담당자 선택(필수), 마감일(필수), 우선순위(필수)
- 유효성 검사: 각 필드별 필수 검증
- 모바일: 전체화면 모달 (100vh), 데스크톱: 중앙 모달 (600px)
- **인터랙션 정의**:
- "추가" 버튼: 빈 모달 표시, 모든 필드 초기화
- "편집" 버튼: 기존 Todo 데이터 로드 및 모달 표시
- "저장" 버튼: 유효성 검사 후 저장, 성공 토스트 표시
- **JavaScript 함수 추가**: addTodoItem(), editTodoItem(todoId), saveTodoItem()
- **프로토타입**: design/uiux/prototype/05-회의진행.html 수정 (~100줄 추가)
- **스타일 가이드**: design/uiux/style-guide.md v1.2.1 (변경 이력 추가)
- **일관성**: 10-회의록상세조회, 09-Todo관리 화면과 Todo 카드 편집 방식 통일 | +| 1.4.12 | 2025-10-23 | 강지수 | 05-회의진행 화면 Todo 카드 스타일 10-회의록상세조회와 완전 통일
- **Todo 카드 HTML 구조 통일**:
- 기존: inline-flex 기반 간소화 구조
- 변경: `.todo-card` > `.todo-top` > (`.todo-checkbox-wrapper` + `.todo-content-wrapper` + `.todo-actions`) 구조
- 10-회의록상세조회.html과 100% 동일한 HTML 구조 적용
- **CSS 스타일 추가**: 페이지 하단 `