mirror of
https://github.com/hwanny1128/HGZero.git
synced 2026-06-12 22:59:10 +00:00
Merge branch 'main' into feature/stt-ai - 로그 파일 충돌 해결
This commit is contained in:
@@ -150,6 +150,7 @@
|
||||
}
|
||||
|
||||
/* 회의 카드 */
|
||||
/* 최근 회의는 최대 3개만 표시하므로 3열로 제한 */
|
||||
.meeting-grid {
|
||||
display: grid;
|
||||
gap: var(--space-md);
|
||||
@@ -168,12 +169,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 1440px) {
|
||||
.meeting-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
}
|
||||
}
|
||||
|
||||
.meeting-card {
|
||||
background: var(--white);
|
||||
border-radius: var(--radius-lg);
|
||||
@@ -238,7 +233,7 @@
|
||||
|
||||
/* Todo 카드 스타일은 common.css에서 공통 관리 */
|
||||
|
||||
/* 통계 영역 - 정보 표시용 (클릭 불가) */
|
||||
/* 통계 영역 - 정보 표시용 (클릭 불가) - UFR-USER-020: 2개 항목 표시 */
|
||||
.stats-overview {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
@@ -513,15 +508,12 @@
|
||||
<div class="sidebar-logo-text">회의록 서비스</div>
|
||||
</a>
|
||||
|
||||
<!-- MVP 스코프 축소: Todo 관리 메뉴 제거 -->
|
||||
<nav class="sidebar-nav">
|
||||
<a href="12-회의록목록조회.html" class="sidebar-nav-item">
|
||||
<span class="sidebar-nav-icon"><img src="img/edit.png" width="32"></span>
|
||||
<span>회의록</span>
|
||||
</a>
|
||||
<a href="09-Todo관리.html" class="sidebar-nav-item">
|
||||
<span class="sidebar-nav-icon"><img src="img/list.png" width="32"></span>
|
||||
<span>Todo 관리</span>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<!-- 사용자 정보 영역 (Desktop) -->
|
||||
@@ -559,7 +551,7 @@
|
||||
<!-- 메인 콘텐츠 -->
|
||||
<main class="main-content">
|
||||
|
||||
<!-- 통계 개요 -->
|
||||
<!-- 통계 개요 (UFR-USER-020) -->
|
||||
<div class="stats-overview">
|
||||
<div class="stat-box stat-meeting">
|
||||
<div class="stat-icon">📅</div>
|
||||
@@ -567,9 +559,9 @@
|
||||
<div class="stat-text">예정된 회의</div>
|
||||
</div>
|
||||
<div class="stat-box stat-todo">
|
||||
<div class="stat-icon">✅</div>
|
||||
<div class="stat-number" id="stat-todos">0</div>
|
||||
<div class="stat-text">나의 Todo</div>
|
||||
<div class="stat-icon">📝</div>
|
||||
<div class="stat-number" id="stat-drafts">0</div>
|
||||
<div class="stat-text">작성중 회의록</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -583,16 +575,7 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 나의 Todo -->
|
||||
<section>
|
||||
<div class="section-header">
|
||||
<h2 class="section-title">나의 Todo</h2>
|
||||
<a href="09-Todo관리.html" class="section-link">전체 보기 →</a>
|
||||
</div>
|
||||
<div class="todo-list" id="my-todos">
|
||||
<!-- 동적 생성 -->
|
||||
</div>
|
||||
</section>
|
||||
<!-- MVP 스코프 축소: "나의 Todo" 섹션 제거 -->
|
||||
|
||||
<!-- 나의 회의록 -->
|
||||
<section>
|
||||
@@ -607,7 +590,7 @@
|
||||
|
||||
</main>
|
||||
|
||||
<!-- 하단 네비게이션 (모바일) -->
|
||||
<!-- 하단 네비게이션 (모바일) - MVP 스코프 축소: Todo 관리 메뉴 제거 -->
|
||||
<nav class="bottom-nav">
|
||||
<a href="02-대시보드.html" class="nav-item active">
|
||||
<img src="img/home.png" alt="홈" style="width: 45px;">
|
||||
@@ -615,9 +598,6 @@
|
||||
<a href="12-회의록목록조회.html" class="nav-item">
|
||||
<img src="img/edit.png" alt="회의록" style="width: 45px;">
|
||||
</a>
|
||||
<a href="09-Todo관리.html" class="nav-item">
|
||||
<img src="img/list.png" alt="Todo" style="width: 45px;">
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<!-- FAB 오버레이 -->
|
||||
@@ -704,8 +684,17 @@
|
||||
const statusInfo = getMeetingStatusInfo(meeting);
|
||||
const isCreator = meeting.participants.some(p => p.id === currentUser.id && p.role === 'creator');
|
||||
|
||||
// 버튼 표시 규칙
|
||||
// - ongoing: 참여하기 버튼 표시
|
||||
// - scheduled: 버튼 없음 (카드 클릭으로 수정 화면 이동)
|
||||
// - draft/complete: 버튼 없음 (카드 클릭으로 상세조회 이동)
|
||||
let actionButton = '';
|
||||
if (meeting.status === 'ongoing') {
|
||||
actionButton = `<button class="btn btn-primary btn-sm" onclick="navigateTo('05-회의진행.html'); event.stopPropagation();">참여하기</button>`;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="meeting-card ${meeting.status === 'ongoing' ? 'ongoing' : ''}" data-id="${meeting.id}">
|
||||
<div class="meeting-card ${meeting.status === 'ongoing' ? 'ongoing' : ''}" data-id="${meeting.id}" data-status="${meeting.status}">
|
||||
<div class="meeting-card-header">
|
||||
${createBadge(statusInfo.badgeText, statusInfo.badgeType)}
|
||||
<h3 class="meeting-card-title">${meeting.title}${isCreator ? ' <span style="font-size: 16px;" title="생성자">👑</span>' : ''}</h3>
|
||||
@@ -714,14 +703,7 @@
|
||||
<div class="meeting-card-meta-item">📅 ${formatDate(meeting.date)} ${formatTime(meeting.time)} 👥 ${meeting.participants.length}명</div>
|
||||
<div class="meeting-card-meta-item">📍 ${meeting.location}</div>
|
||||
</div>
|
||||
<div class="meeting-card-actions">
|
||||
${meeting.status === 'ongoing'
|
||||
? `<button class="btn btn-primary btn-sm" onclick="navigateTo('05-회의진행.html'); event.stopPropagation();">참여하기</button>`
|
||||
: meeting.status === 'scheduled' && isCreator
|
||||
? `<button class="btn btn-secondary btn-sm" onclick="navigateTo('03-회의예약.html'); event.stopPropagation();">수정</button>`
|
||||
: `<button class="btn btn-ghost btn-sm" onclick="navigateTo('10-회의록상세조회.html'); event.stopPropagation();">보기</button>`
|
||||
}
|
||||
</div>
|
||||
${actionButton ? `<div class="meeting-card-actions">${actionButton}</div>` : ''}
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
@@ -731,12 +713,14 @@
|
||||
card.addEventListener('click', (e) => {
|
||||
if (e.target.tagName !== 'BUTTON') {
|
||||
const meetingId = card.dataset.id;
|
||||
const meeting = SAMPLE_MEETINGS.find(m => m.id === meetingId);
|
||||
if (meeting.status === 'ongoing') {
|
||||
const meetingStatus = card.dataset.status;
|
||||
|
||||
// 상태에 따른 이동 처리
|
||||
if (meetingStatus === 'ongoing') {
|
||||
navigateTo('05-회의진행.html');
|
||||
} else if (meeting.status === 'completed') {
|
||||
} else if (meetingStatus === 'draft' || meetingStatus === 'complete' || meetingStatus === 'completed') {
|
||||
navigateTo('10-회의록상세조회.html');
|
||||
} else {
|
||||
} else if (meetingStatus === 'scheduled') {
|
||||
navigateTo('03-회의예약.html');
|
||||
}
|
||||
}
|
||||
@@ -745,104 +729,9 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 내 Todo 렌더링 (09-Todo관리.html과 동일한 정렬 기준)
|
||||
* MVP 스코프 축소: renderMyTodos() 함수 제거됨
|
||||
* 대시보드에서 Todo 위젯이 제거되어 더 이상 사용되지 않음
|
||||
*/
|
||||
function renderMyTodos() {
|
||||
const container = $('#my-todos');
|
||||
|
||||
const myTodos = SAMPLE_TODOS
|
||||
.filter(todo => todo.assignee.id === currentUser.id)
|
||||
.sort((a, b) => {
|
||||
// 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, 3); // 상위 3개만 표시
|
||||
|
||||
if (myTodos.length === 0) {
|
||||
container.innerHTML = '<div class="empty-state"><div class="empty-icon">✅</div><p>할당된 Todo가 없습니다</p></div>';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = myTodos.map(todo => {
|
||||
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 = 'badge-secondary';
|
||||
}
|
||||
|
||||
// 우선순위 배지
|
||||
const priorityText = todo.priority === 'high' ? '높음' : todo.priority === 'medium' ? '보통' : '낮음';
|
||||
const priorityClass = `badge-${todo.priority}`;
|
||||
|
||||
return `
|
||||
<div class="todo-card ${isCompleted ? 'completed' : ''}" data-todo-id="${todo.id}" data-meeting-id="${todo.meetingId}">
|
||||
<div class="todo-top">
|
||||
<div class="todo-checkbox-wrapper">
|
||||
<input type="checkbox" class="todo-checkbox" id="check-${todo.id}"
|
||||
${isCompleted ? 'checked' : ''}
|
||||
onchange="toggleTodoComplete('${todo.id}', this.checked)">
|
||||
</div>
|
||||
<div class="todo-content-wrapper">
|
||||
<div class="todo-badges">
|
||||
<span class="badge ${ddayClass}">${ddayBadge}</span>
|
||||
<span class="badge ${priorityClass}">${priorityText}</span>
|
||||
</div>
|
||||
<div class="todo-title">${todo.title}</div>
|
||||
<div class="todo-meta-row">
|
||||
<a class="todo-meeting-link" onclick="navigateTo('10-회의록상세조회.html'); event.stopPropagation();">
|
||||
🔗 ${todo.meetingTitle}
|
||||
</a>
|
||||
<span>${formatDate(todo.dueDate)}</span>
|
||||
</div>
|
||||
</div>
|
||||
${!isCompleted ? `
|
||||
<div class="todo-actions">
|
||||
<button class="icon-btn" onclick="editTodo('${todo.id}')" title="편집">✏️</button>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('');
|
||||
|
||||
// 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}`);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 나의 회의록 렌더링 (참여자 또는 생성자로 등록된 회의록, 최신순 정렬)
|
||||
@@ -887,31 +776,33 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* 통계 업데이트
|
||||
* 통계 업데이트 (UFR-USER-020)
|
||||
*/
|
||||
function updateStats() {
|
||||
// 예정된 회의 개수 (예정 + 진행중)
|
||||
const scheduled = SAMPLE_MEETINGS.filter(m => m.status === 'scheduled' || m.status === 'ongoing').length;
|
||||
|
||||
// 나의 Todo 개수 (전체)
|
||||
const myTodos = SAMPLE_TODOS.filter(t => t.assignee.id === currentUser.id).length;
|
||||
// 작성중 회의록 개수 (내가 참석한 회의 중 '작성중' 상태)
|
||||
const drafts = SAMPLE_MINUTES.filter(m =>
|
||||
m.status === 'draft' &&
|
||||
m.participants.some(p => p.id === currentUser.id)
|
||||
).length;
|
||||
|
||||
$('#stat-scheduled').textContent = scheduled;
|
||||
$('#stat-todos').textContent = myTodos;
|
||||
$('#stat-drafts').textContent = drafts;
|
||||
}
|
||||
|
||||
/**
|
||||
* 초기화
|
||||
* 초기화 - MVP 스코프 축소: renderMyTodos() 제거
|
||||
*/
|
||||
function init() {
|
||||
renderSidebarUser();
|
||||
renderHeader();
|
||||
updateStats();
|
||||
renderRecentMeetings();
|
||||
renderMyTodos();
|
||||
renderMyMinutes();
|
||||
|
||||
console.log('대시보드 초기화 완료');
|
||||
console.log('대시보드 초기화 완료 (MVP 스코프 축소)');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1002,48 +893,11 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Todo 완료 토글
|
||||
* @param {string} todoId - Todo ID
|
||||
* @param {boolean} isChecked - 체크박스 상태
|
||||
* MVP 스코프 축소: Todo 관련 함수 제거됨
|
||||
* - toggleTodoComplete()
|
||||
* - editTodo()
|
||||
* 대시보드에서 Todo 위젯이 제거되어 더 이상 사용되지 않음
|
||||
*/
|
||||
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();
|
||||
</script>
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
}
|
||||
|
||||
.meeting-title {
|
||||
font-size: var(--font-large);
|
||||
font-size: var(--font-h2);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--gray-800);
|
||||
margin: 0;
|
||||
@@ -100,7 +100,7 @@
|
||||
}
|
||||
|
||||
.recording-time {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-medium);
|
||||
}
|
||||
|
||||
@@ -173,9 +173,9 @@
|
||||
.info-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
padding: var(--space-xs) 0;
|
||||
align-items: flex-start;
|
||||
gap: 0;
|
||||
padding: var(--space-sm) 0;
|
||||
border-bottom: 1px solid var(--gray-300);
|
||||
}
|
||||
|
||||
@@ -186,14 +186,28 @@
|
||||
.info-label {
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--gray-600);
|
||||
font-size: var(--font-caption);
|
||||
min-width: 60px;
|
||||
font-size: var(--font-small);
|
||||
width: 70px;
|
||||
min-width: 70px;
|
||||
max-width: 70px;
|
||||
flex-shrink: 0;
|
||||
padding-right: var(--space-sm);
|
||||
border-right: 1px solid var(--gray-300);
|
||||
margin-right: var(--space-sm);
|
||||
}
|
||||
|
||||
/* 데스크톱에서 라벨 폭 확장 */
|
||||
@media (min-width: 768px) {
|
||||
.info-label {
|
||||
width: 100px;
|
||||
min-width: 100px;
|
||||
max-width: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.info-value {
|
||||
color: var(--gray-800);
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
line-height: 1.5;
|
||||
flex: 1;
|
||||
}
|
||||
@@ -229,7 +243,7 @@
|
||||
background: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--gray-600);
|
||||
transition: all var(--transition-fast);
|
||||
@@ -289,13 +303,13 @@
|
||||
}
|
||||
|
||||
.participant-section-title {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-bold);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.participant-count {
|
||||
font-size: var(--font-caption);
|
||||
font-size: var(--font-small);
|
||||
color: var(--gray-600);
|
||||
}
|
||||
|
||||
@@ -307,13 +321,13 @@
|
||||
|
||||
.invite-input {
|
||||
flex: 1;
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
padding: var(--space-sm);
|
||||
}
|
||||
|
||||
.invite-btn {
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -337,13 +351,13 @@
|
||||
}
|
||||
|
||||
.participant-name {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--gray-800);
|
||||
}
|
||||
|
||||
.participant-email {
|
||||
font-size: var(--font-caption);
|
||||
font-size: var(--font-small);
|
||||
color: var(--gray-500);
|
||||
margin-top: 2px;
|
||||
overflow: hidden;
|
||||
@@ -351,7 +365,7 @@
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
/* AI 제안 탭 */
|
||||
/* AI 기반 메모 탭 - MVP 스코프 축소 v1.5.1 */
|
||||
.memo-input-section {
|
||||
background: var(--gray-50);
|
||||
border-radius: var(--radius-md);
|
||||
@@ -360,7 +374,7 @@
|
||||
}
|
||||
|
||||
.memo-input-label {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--gray-700);
|
||||
margin-bottom: var(--space-xs);
|
||||
@@ -373,7 +387,7 @@
|
||||
padding: var(--space-sm);
|
||||
border: 1px solid var(--gray-300);
|
||||
border-radius: var(--radius-md);
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-family: inherit;
|
||||
resize: vertical;
|
||||
line-height: 1.5;
|
||||
@@ -388,17 +402,17 @@
|
||||
width: 100%;
|
||||
margin-top: var(--space-xs);
|
||||
padding: var(--space-sm);
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
}
|
||||
|
||||
.ai-suggestion-list-title {
|
||||
font-size: var(--font-body);
|
||||
font-size: var(--font-h3);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--gray-900);
|
||||
margin-bottom: var(--space-sm);
|
||||
}
|
||||
|
||||
/* AI 제안 카드 */
|
||||
/* AI 주요 내용 카드 */
|
||||
.ai-suggestion-card {
|
||||
background: #FAFAFA;
|
||||
border: 1px dashed #D0D0D0;
|
||||
@@ -416,7 +430,7 @@
|
||||
}
|
||||
|
||||
.ai-suggestion-time {
|
||||
font-size: var(--font-caption);
|
||||
font-size: var(--font-small);
|
||||
color: var(--gray-500);
|
||||
font-weight: var(--font-weight-regular);
|
||||
}
|
||||
@@ -446,7 +460,7 @@
|
||||
}
|
||||
|
||||
.ai-suggestion-text {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
color: var(--gray-700);
|
||||
line-height: 1.5;
|
||||
}
|
||||
@@ -460,13 +474,13 @@
|
||||
|
||||
.term-search-input {
|
||||
flex: 1;
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
padding: var(--space-sm);
|
||||
}
|
||||
|
||||
.term-search-btn {
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
@@ -493,7 +507,7 @@
|
||||
}
|
||||
|
||||
.term-name {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--primary);
|
||||
display: flex;
|
||||
@@ -512,14 +526,14 @@
|
||||
}
|
||||
|
||||
.term-definition {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
color: var(--gray-700);
|
||||
line-height: 1.5;
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
|
||||
.term-context {
|
||||
font-size: 11px;
|
||||
font-size: var(--font-small);
|
||||
color: var(--gray-500);
|
||||
padding-top: var(--space-xs);
|
||||
border-top: 1px dashed #D0D0D0;
|
||||
@@ -546,7 +560,7 @@
|
||||
}
|
||||
|
||||
.related-doc-title {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--primary);
|
||||
margin-bottom: var(--space-xs);
|
||||
@@ -555,7 +569,7 @@
|
||||
.related-doc-meta {
|
||||
display: flex;
|
||||
gap: var(--space-xs);
|
||||
font-size: var(--font-caption);
|
||||
font-size: var(--font-small);
|
||||
color: var(--gray-600);
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
@@ -566,7 +580,7 @@
|
||||
}
|
||||
|
||||
.related-doc-text {
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
color: var(--gray-700);
|
||||
line-height: 1.5;
|
||||
}
|
||||
@@ -668,7 +682,7 @@
|
||||
참석자
|
||||
</button>
|
||||
<button class="tab-button" onclick="switchTab('ai-suggestions')">
|
||||
AI 제안
|
||||
AI 메모
|
||||
</button>
|
||||
<button class="tab-button" onclick="switchTab('terms')">
|
||||
용어사전
|
||||
@@ -732,7 +746,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI 제안 탭 -->
|
||||
<!-- AI 기반 메모 탭 (MVP 스코프 축소 v1.5.1) -->
|
||||
<div class="tab-content" id="tab-ai-suggestions">
|
||||
<div class="memo-input-section">
|
||||
<label class="memo-input-label">📝 회의 메모</label>
|
||||
@@ -1053,7 +1067,7 @@
|
||||
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
||||
}
|
||||
|
||||
// AI 제안을 메모에 추가
|
||||
// AI가 감지한 주요 내용을 메모에 추가 (MVP 스코프 축소 v1.5.1)
|
||||
function addToMemo(suggestionText, cardElement) {
|
||||
const memoTextarea = document.getElementById('meetingMemo');
|
||||
const currentMemo = memoTextarea.value;
|
||||
@@ -1062,7 +1076,7 @@
|
||||
const recordingTime = document.getElementById('recordingTime').textContent;
|
||||
const timePrefix = '[' + recordingTime.substring(0, 5) + '] '; // HH:MM만 추출
|
||||
|
||||
// 시간 정보 + 제안 내용
|
||||
// 시간 정보 + 주요 내용
|
||||
const memoWithTime = timePrefix + suggestionText;
|
||||
|
||||
if (currentMemo) {
|
||||
@@ -1071,7 +1085,7 @@
|
||||
memoTextarea.value = memoWithTime;
|
||||
}
|
||||
|
||||
// AI 제안 카드 삭제
|
||||
// AI 주요 내용 카드 삭제 (선택 후 제거)
|
||||
if (cardElement) {
|
||||
cardElement.remove();
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -107,11 +107,41 @@
|
||||
margin-bottom: var(--space-md);
|
||||
}
|
||||
|
||||
/* 회의 제목 컨테이너 */
|
||||
.meeting-title-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
margin-bottom: var(--space-md);
|
||||
}
|
||||
|
||||
/* 배지 영역 (배지 + 크라운) */
|
||||
.meeting-badges {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-xs);
|
||||
}
|
||||
|
||||
/* 회의 제목 */
|
||||
.meeting-basic-info h2 {
|
||||
font-size: var(--font-h2);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--gray-900);
|
||||
margin-bottom: var(--space-sm);
|
||||
margin: 0;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
/* 데스크톱: 기존 가로 배치 유지 */
|
||||
@media (min-width: 768px) {
|
||||
.meeting-title-container {
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.meeting-basic-info h2 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info-row {
|
||||
@@ -165,23 +195,6 @@
|
||||
.participant {
|
||||
width: calc(50% - var(--space-md) / 2);
|
||||
}
|
||||
|
||||
/* 통계 그리드: 모바일에서도 4열 유지, gap만 축소 */
|
||||
.stats-grid {
|
||||
gap: var(--space-xs);
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
padding: var(--space-sm);
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: var(--font-base);
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
font-size: var(--font-xs);
|
||||
}
|
||||
}
|
||||
|
||||
/* 회의록 섹션 */
|
||||
@@ -279,22 +292,6 @@
|
||||
margin-bottom: var(--space-md);
|
||||
}
|
||||
|
||||
.reference-item {
|
||||
background: var(--white);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-sm);
|
||||
margin-bottom: var(--space-sm);
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
}
|
||||
|
||||
.reference-item:hover {
|
||||
box-shadow: var(--shadow-sm);
|
||||
}
|
||||
|
||||
.reference-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.reference-header {
|
||||
display: flex;
|
||||
@@ -310,7 +307,7 @@
|
||||
|
||||
.reference-title {
|
||||
flex: 1;
|
||||
font-size: var(--font-small);
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--gray-900);
|
||||
}
|
||||
@@ -338,7 +335,7 @@
|
||||
}
|
||||
|
||||
.reference-meta {
|
||||
font-size: var(--font-caption);
|
||||
font-size: var(--font-small);
|
||||
color: var(--gray-500);
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
@@ -405,10 +402,11 @@
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
/* 통계 그리드 - 모바일 기본 (2x2) */
|
||||
.stats-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: var(--space-md);
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: var(--space-sm);
|
||||
margin-top: var(--space-md);
|
||||
}
|
||||
|
||||
@@ -431,6 +429,14 @@
|
||||
color: var(--gray-500);
|
||||
}
|
||||
|
||||
/* 데스크톱: 1x4 그리드 */
|
||||
@media (min-width: 768px) {
|
||||
.stats-grid {
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: var(--space-md);
|
||||
}
|
||||
}
|
||||
|
||||
/* 결정사항 카드 */
|
||||
.decision-card {
|
||||
background: var(--white);
|
||||
@@ -462,7 +468,7 @@
|
||||
border-top: 1px solid var(--gray-300);
|
||||
}
|
||||
|
||||
/* Todo 진행상황 */
|
||||
/* Todo 리스트 */
|
||||
.todo-filters {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
@@ -523,7 +529,64 @@
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
|
||||
/* Todo 진행상황 - 09-Todo관리 스타일 적용 */
|
||||
/* Todo 리스트 - 단순 조회 스타일 */
|
||||
.simple-todo-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.simple-todo-item {
|
||||
position: relative;
|
||||
padding: var(--space-md);
|
||||
background: var(--white);
|
||||
border-radius: var(--radius-md);
|
||||
border: 1px solid var(--gray-300);
|
||||
}
|
||||
|
||||
.simple-todo-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: var(--space-sm);
|
||||
margin-bottom: var(--space-xs);
|
||||
}
|
||||
|
||||
.simple-todo-title {
|
||||
flex: 1;
|
||||
font-size: var(--font-body);
|
||||
font-weight: var(--font-weight-medium);
|
||||
color: var(--gray-900);
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.simple-todo-edit-btn {
|
||||
background: transparent;
|
||||
border: none;
|
||||
font-size: 20px;
|
||||
cursor: pointer;
|
||||
padding: 4px;
|
||||
color: var(--gray-500);
|
||||
transition: all var(--transition-fast);
|
||||
flex-shrink: 0;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.simple-todo-edit-btn:hover {
|
||||
color: var(--primary);
|
||||
background: var(--primary-light);
|
||||
transform: scale(1.1);
|
||||
}
|
||||
|
||||
.simple-todo-meta {
|
||||
font-size: var(--font-small);
|
||||
color: var(--gray-600);
|
||||
display: flex;
|
||||
gap: var(--space-md);
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* Todo 리스트 - 09-Todo관리 스타일 적용 */
|
||||
.todo-filters {
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
@@ -688,6 +751,24 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* 대시보드 탭의 관련회의록 카드 스타일 강화 */
|
||||
.card .reference-item {
|
||||
border: 1px solid var(--gray-200) !important;
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08) !important;
|
||||
margin-bottom: var(--space-sm) !important;
|
||||
}
|
||||
|
||||
.card .reference-item:hover {
|
||||
border-color: var(--primary) !important;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12) !important;
|
||||
transform: translateY(-1px) !important;
|
||||
}
|
||||
|
||||
.card .reference-item:active {
|
||||
transform: translateY(0) !important;
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08) !important;
|
||||
}
|
||||
|
||||
/* 모바일 화면에서 관련회의록 왼쪽 정렬 */
|
||||
@media (max-width: 600px) {
|
||||
.reference-item {
|
||||
@@ -738,10 +819,14 @@
|
||||
<!-- 기본 정보 카드 -->
|
||||
<div class="info-card">
|
||||
<div class="meeting-basic-info">
|
||||
<div id="meeting-title-container" style="display: flex; align-items: center; gap: var(--space-sm); margin-bottom: var(--space-sm);">
|
||||
<span class="badge badge-complete">확정완료</span>
|
||||
<!-- 생성자일 경우 👑 아이콘이 JavaScript로 추가됨 -->
|
||||
<h2 style="margin: 0;">2025년 1분기 제품 기획 회의</h2>
|
||||
<div class="meeting-title-container">
|
||||
<!-- 배지 + 크라운 영역 -->
|
||||
<div class="meeting-badges" id="meeting-badges">
|
||||
<span class="badge badge-complete">확정완료</span>
|
||||
<!-- 생성자일 경우 👑 아이콘이 JavaScript로 추가됨 -->
|
||||
</div>
|
||||
<!-- 회의 제목 -->
|
||||
<h2>2025년 1분기 제품 기획 회의</h2>
|
||||
</div>
|
||||
<div class="info-row">
|
||||
<span class="info-icon">📅</span>
|
||||
@@ -757,7 +842,7 @@
|
||||
<div class="participant">
|
||||
<div class="avatar avatar-green">김</div>
|
||||
<span class="participant-name">김민준</span>
|
||||
<span class="role-badge">작성자</span>
|
||||
<span class="role-badge">생성자</span>
|
||||
</div>
|
||||
<div class="participant">
|
||||
<div class="avatar avatar-blue">박</div>
|
||||
@@ -1042,148 +1127,70 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Todo 진행상황 -->
|
||||
<!-- Todo 단순 조회 (MVP 스코프 축소 v1.5.1) -->
|
||||
<div class="card mb-lg">
|
||||
<h3 class="card-title">📋 Todo 진행상황</h3>
|
||||
|
||||
<!-- 전체 진행률 -->
|
||||
<div style="margin-bottom: var(--space-lg);">
|
||||
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--space-xs);">
|
||||
<span style="font-size: var(--font-body); font-weight: var(--font-weight-medium); color: var(--gray-900);">전체 진행률</span>
|
||||
<span style="font-size: var(--font-body); font-weight: var(--font-weight-bold); color: var(--primary);">40%</span>
|
||||
</div>
|
||||
<div style="width: 100%; height: 8px; background: var(--gray-200); border: 1px solid var(--gray-300); border-radius: 4px; overflow: hidden;">
|
||||
<div style="width: 40%; height: 100%; background: var(--primary); transition: width 0.3s ease;"></div>
|
||||
</div>
|
||||
<div style="font-size: var(--font-caption); color: var(--gray-600); margin-top: var(--space-xs);">
|
||||
2 / 5 완료
|
||||
</div>
|
||||
<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);">
|
||||
Todo 항목은 조회만 가능합니다. 제목, 담당자, 마감일 정보만 표시됩니다.
|
||||
</p>
|
||||
|
||||
<div class="todo-filters">
|
||||
<button class="filter-btn active" data-filter="all" onclick="filterTodos('all')">
|
||||
전체 (<span id="filterAllCount">5</span>)
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="overdue" onclick="filterTodos('overdue')">
|
||||
지연 (<span id="filterOverdueCount">1</span>)
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="urgent" onclick="filterTodos('urgent')">
|
||||
마감 임박 (<span id="filterUrgentCount">2</span>)
|
||||
</button>
|
||||
<button class="filter-btn" data-filter="completed" onclick="filterTodos('completed')">
|
||||
완료 (<span id="filterCompletedCount">2</span>)
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Todo 카드 리스트 -->
|
||||
<div class="todo-card">
|
||||
<div class="todo-top">
|
||||
<div class="todo-checkbox-wrapper">
|
||||
<input type="checkbox" class="todo-checkbox" id="check-todo-002"
|
||||
onchange="toggleTodoComplete('todo-002', this.checked)">
|
||||
<!-- Todo 단순 조회 리스트 (제목 + 담당자 + 마감일 + 수정 버튼) -->
|
||||
<div class="simple-todo-list">
|
||||
<div class="simple-todo-item">
|
||||
<div class="simple-todo-header">
|
||||
<div class="simple-todo-title">데이터베이스 스키마 설계</div>
|
||||
<button class="simple-todo-edit-btn creator-only" onclick="editTodo(1)" title="수정">✏️</button>
|
||||
</div>
|
||||
<div class="todo-content-wrapper">
|
||||
<div class="todo-badges">
|
||||
<span class="badge badge-overdue">D+1 (지연)</span>
|
||||
<span class="badge badge-high">높음</span>
|
||||
</div>
|
||||
<div class="todo-title">데이터베이스 스키마 설계</div>
|
||||
<div class="todo-meta-row">
|
||||
<span>담당자: 이준호</span>
|
||||
<span>2025-10-20 마감</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="icon-btn" onclick="editTodo('todo-002')" title="편집">✏️</button>
|
||||
<div class="simple-todo-meta">
|
||||
<span>👤 이준호</span>
|
||||
<span>📅 2025-10-20</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="todo-card">
|
||||
<div class="todo-top">
|
||||
<div class="todo-checkbox-wrapper">
|
||||
<input type="checkbox" class="todo-checkbox" id="check-todo-001"
|
||||
onchange="toggleTodoComplete('todo-001', this.checked)">
|
||||
<div class="simple-todo-item">
|
||||
<div class="simple-todo-header">
|
||||
<div class="simple-todo-title">API 명세서 작성</div>
|
||||
<button class="simple-todo-edit-btn creator-only" onclick="editTodo(2)" title="수정">✏️</button>
|
||||
</div>
|
||||
<div class="todo-content-wrapper">
|
||||
<div class="todo-badges">
|
||||
<span class="badge badge-warning">D-2</span>
|
||||
<span class="badge badge-high">높음</span>
|
||||
</div>
|
||||
<div class="todo-title">API 명세서 작성</div>
|
||||
<div class="todo-meta-row">
|
||||
<span>담당자: 이준호</span>
|
||||
<span>2025-10-23 마감</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="icon-btn" onclick="editTodo('todo-001')" title="편집">✏️</button>
|
||||
<div class="simple-todo-meta">
|
||||
<span>👤 이준호</span>
|
||||
<span>📅 2025-10-23</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="todo-card">
|
||||
<div class="todo-top">
|
||||
<div class="todo-checkbox-wrapper">
|
||||
<input type="checkbox" class="todo-checkbox" id="check-todo-005"
|
||||
onchange="toggleTodoComplete('todo-005', this.checked)">
|
||||
<div class="simple-todo-item">
|
||||
<div class="simple-todo-header">
|
||||
<div class="simple-todo-title">예산 편성안 검토</div>
|
||||
<button class="simple-todo-edit-btn creator-only" onclick="editTodo(3)" title="수정">✏️</button>
|
||||
</div>
|
||||
<div class="todo-content-wrapper">
|
||||
<div class="todo-badges">
|
||||
<span class="badge badge-warning">D-1</span>
|
||||
<span class="badge badge-high">높음</span>
|
||||
</div>
|
||||
<div class="todo-title">예산 편성안 검토</div>
|
||||
<div class="todo-meta-row">
|
||||
<span>담당자: 김민준</span>
|
||||
<span>2025-10-22 마감</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="icon-btn" onclick="editTodo('todo-005')" title="편집">✏️</button>
|
||||
<div class="simple-todo-meta">
|
||||
<span>👤 김민준</span>
|
||||
<span>📅 2025-10-22</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="todo-card">
|
||||
<div class="todo-top">
|
||||
<div class="todo-checkbox-wrapper">
|
||||
<input type="checkbox" class="todo-checkbox" id="check-todo-003"
|
||||
onchange="toggleTodoComplete('todo-003', this.checked)">
|
||||
<div class="simple-todo-item">
|
||||
<div class="simple-todo-header">
|
||||
<div class="simple-todo-title">UI 프로토타입 디자인</div>
|
||||
<button class="simple-todo-edit-btn creator-only" onclick="editTodo(4)" title="수정">✏️</button>
|
||||
</div>
|
||||
<div class="todo-content-wrapper">
|
||||
<div class="todo-badges">
|
||||
<span class="badge badge-primary">D-7</span>
|
||||
<span class="badge badge-medium">보통</span>
|
||||
</div>
|
||||
<div class="todo-title">UI 프로토타입 디자인</div>
|
||||
<div class="todo-meta-row">
|
||||
<span>담당자: 최유진</span>
|
||||
<span>2025-10-28 마감</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="todo-actions">
|
||||
<button class="icon-btn" onclick="editTodo('todo-003')" title="편집">✏️</button>
|
||||
<div class="simple-todo-meta">
|
||||
<span>👤 최유진</span>
|
||||
<span>📅 2025-10-28</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="todo-card completed">
|
||||
<div class="todo-top">
|
||||
<div class="todo-checkbox-wrapper">
|
||||
<input type="checkbox" class="todo-checkbox" id="check-todo-004" checked
|
||||
onchange="toggleTodoComplete('todo-004', this.checked)">
|
||||
<div class="simple-todo-item">
|
||||
<div class="simple-todo-header">
|
||||
<div class="simple-todo-title">사용자 피드백 분석</div>
|
||||
<button class="simple-todo-edit-btn creator-only" onclick="editTodo(5)" title="수정">✏️</button>
|
||||
</div>
|
||||
<div class="todo-content-wrapper">
|
||||
<div class="todo-badges">
|
||||
<span class="badge badge-complete">완료</span>
|
||||
<span class="badge badge-medium">보통</span>
|
||||
</div>
|
||||
<div class="todo-title">사용자 피드백 분석</div>
|
||||
<div class="todo-meta-row">
|
||||
<span>담당자: 김민준</span>
|
||||
<span>2025-10-19 마감</span>
|
||||
</div>
|
||||
<div class="simple-todo-meta">
|
||||
<span>👤 김민준</span>
|
||||
<span>📅 2025-10-19</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1199,7 +1206,7 @@
|
||||
<span class="reference-title">AI 기능 개선 회의</span>
|
||||
<span class="relevance-badge relevance-high">92%</span>
|
||||
</div>
|
||||
<div class="reference-meta">2025-10-23 15:00 · 이준호</div>
|
||||
<div class="reference-meta">이준호 · 2025-10-23 15:00</div>
|
||||
<div class="reference-summary">
|
||||
AI 요약 정확도 개선 방안 논의. BERT 모델 도입 및 학습 데이터 확보 계획 수립.
|
||||
</div>
|
||||
@@ -1211,7 +1218,7 @@
|
||||
<span class="reference-title">개발 리소스 계획 회의</span>
|
||||
<span class="relevance-badge relevance-medium">88%</span>
|
||||
</div>
|
||||
<div class="reference-meta">2025-10-22 11:00 · 김민준</div>
|
||||
<div class="reference-meta">김민준 · 2025-10-22 11:00</div>
|
||||
<div class="reference-summary">
|
||||
Q4 개발 리소스 현황 및 배분 계획. 신규 프로젝트 우선순위 협의.
|
||||
</div>
|
||||
@@ -1223,7 +1230,7 @@
|
||||
<span class="reference-title">경쟁사 분석 회의</span>
|
||||
<span class="relevance-badge relevance-medium">78%</span>
|
||||
</div>
|
||||
<div class="reference-meta">2025-10-20 10:00 · 박서연</div>
|
||||
<div class="reference-meta">박서연 · 2025-10-20 10:00</div>
|
||||
<div class="reference-summary">
|
||||
경쟁사 A, B, C 분석 결과. 우리의 차별점은 실시간 협업 및 검증 기능.
|
||||
</div>
|
||||
@@ -1237,6 +1244,43 @@
|
||||
<button class="btn btn-secondary" onclick="navigateTo('11-회의록수정.html')">수정</button>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Todo 추가 모달 -->
|
||||
<div class="modal-overlay" id="addTodoModal">
|
||||
<div class="modal">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">Todo 추가</h3>
|
||||
<button class="modal-close" onclick="closeModal('addTodoModal')">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Todo 내용 <span class="text-error">*</span></label>
|
||||
<input type="text" id="addTodoTitle" class="form-control" placeholder="할 일을 입력하세요">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<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">
|
||||
<input type="date" id="addTodoDueDate" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-ghost" onclick="closeModal('addTodoModal')">취소</button>
|
||||
<button class="btn btn-primary" onclick="addTodo()">추가</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Todo 편집 모달 -->
|
||||
<div class="modal-overlay" id="editTodoModal">
|
||||
<div class="modal">
|
||||
@@ -1245,6 +1289,7 @@
|
||||
<button class="modal-close" onclick="closeModal('editTodoModal')">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<input type="hidden" id="editTodoId">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Todo 제목 <span class="text-error">*</span></label>
|
||||
<input type="text" id="editTodoTitle" class="form-control" placeholder="할 일을 입력하세요">
|
||||
@@ -1258,30 +1303,12 @@
|
||||
<option value="박서연">박서연</option>
|
||||
<option value="최유진">최유진</option>
|
||||
</select>
|
||||
<p class="form-hint">👤 담당자 변경 시 이전/새 담당자에게 알림이 전송됩니다</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">마감일 <span class="text-error">*</span></label>
|
||||
<div class="date-input-wrapper">
|
||||
<input type="date" id="editTodoDueDate" class="form-control">
|
||||
</div>
|
||||
<p class="form-hint">📅 마감일 변경 시 캘린더가 자동 업데이트됩니다</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">우선순위 <span class="text-error">*</span></label>
|
||||
<select id="editTodoPriority" class="form-control">
|
||||
<option value="high">높음</option>
|
||||
<option value="medium">보통</option>
|
||||
<option value="low">낮음</option>
|
||||
</select>
|
||||
</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 class="modal-footer">
|
||||
@@ -1323,95 +1350,39 @@
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
/* Todo 편집 모달 - 모바일 전체화면 */
|
||||
/* Todo 추가/편집 모달 - 바텀시트 스타일 */
|
||||
#addTodoModal .modal,
|
||||
#editTodoModal .modal {
|
||||
position: fixed;
|
||||
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;
|
||||
max-height: 90vh;
|
||||
overflow-y: auto;
|
||||
padding: var(--space-lg) var(--space-md);
|
||||
-webkit-overflow-scrolling: touch;
|
||||
}
|
||||
|
||||
#addTodoModal .modal-footer,
|
||||
#editTodoModal .modal-footer {
|
||||
flex-shrink: 0;
|
||||
padding: var(--space-md);
|
||||
border-top: 1px solid var(--gray-200);
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
background: var(--white);
|
||||
justify-content: flex-end;
|
||||
margin-top: var(--space-md);
|
||||
}
|
||||
|
||||
#addTodoModal .modal-footer .btn,
|
||||
#editTodoModal .modal-footer .btn {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
/* 데스크톱에서는 중앙 모달로 복원 */
|
||||
/* 데스크톱에서는 중앙 모달 */
|
||||
@media (min-width: 768px) {
|
||||
#addTodoModal .modal,
|
||||
#editTodoModal .modal {
|
||||
position: relative;
|
||||
top: auto;
|
||||
left: auto;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
width: 90%;
|
||||
max-width: 600px;
|
||||
height: auto;
|
||||
max-height: 90vh;
|
||||
margin: 0 auto;
|
||||
border-radius: var(--radius-lg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 회의 생성자 전용 요소 숨김 */
|
||||
.creator-only.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script src="common.js"></script>
|
||||
@@ -1460,24 +1431,17 @@
|
||||
}
|
||||
|
||||
/**
|
||||
* Todo 필터링 (09-Todo관리와 동일)
|
||||
* MVP 스코프 축소 v1.5.1: Todo 필터링/편집 함수 제거됨
|
||||
* 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 필터링 기능
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Todo 편집 모달 열기
|
||||
* @param {string} todoId - 편집할 Todo ID
|
||||
*/
|
||||
/*
|
||||
function editTodo(todoId) {
|
||||
const todo = meetingTodos.find(t => t.id === todoId);
|
||||
if (!todo) return;
|
||||
@@ -1610,39 +1574,13 @@
|
||||
* @param {string} todoId - Todo ID
|
||||
* @param {boolean} isChecked - 체크박스 상태
|
||||
*/
|
||||
/*
|
||||
function toggleTodoComplete(todoId, isChecked) {
|
||||
if (isChecked) {
|
||||
// 완료 처리
|
||||
if (confirm('완료 처리하시겠습니까?')) {
|
||||
const todo = meetingTodos.find(t => t.id === todoId);
|
||||
if (todo) {
|
||||
todo.status = 'completed';
|
||||
showToast('Todo가 완료되었습니다', 'success');
|
||||
updateTodoProgress();
|
||||
renderTodoList();
|
||||
}
|
||||
} else {
|
||||
event.target.checked = false;
|
||||
}
|
||||
} else {
|
||||
// 미완료로 되돌리기
|
||||
if (confirm('미완료로 변경하시겠습니까?')) {
|
||||
const todo = meetingTodos.find(t => t.id === todoId);
|
||||
if (todo) {
|
||||
todo.status = 'incomplete';
|
||||
showToast('미완료로 변경되었습니다', 'info');
|
||||
updateTodoProgress();
|
||||
renderTodoList();
|
||||
}
|
||||
} else {
|
||||
event.target.checked = true;
|
||||
}
|
||||
}
|
||||
// 제거됨: Todo 완료 토글 기능
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Todo 진행률 업데이트
|
||||
*/
|
||||
/*
|
||||
function updateTodoProgress() {
|
||||
const total = meetingTodos.length;
|
||||
const completed = meetingTodos.filter(t => t.status === 'completed').length;
|
||||
@@ -1731,6 +1669,191 @@
|
||||
if (filterCompletedCount) filterCompletedCount.textContent = completed;
|
||||
}
|
||||
|
||||
/**
|
||||
* 회의 생성자 여부 확인
|
||||
* @param {string} meetingId - 회의 ID
|
||||
* @param {string} userName - 사용자 이름
|
||||
* @returns {boolean} 회의 생성자 여부
|
||||
*/
|
||||
function checkIfUserIsCreator(meetingId, userName) {
|
||||
// 실제로는 서버 API를 호출하여 확인
|
||||
// 프로토타입에서는 샘플 데이터로 시뮬레이션
|
||||
const meetingCreators = {
|
||||
'meeting-001': '김민준',
|
||||
'meeting-002': '이서연',
|
||||
'meeting-003': '박준호'
|
||||
};
|
||||
|
||||
return meetingCreators[meetingId] === userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Todo 수정 함수 (index 기반)
|
||||
* @param {number} index - Todo 인덱스 (1-based)
|
||||
*/
|
||||
function editTodo(index) {
|
||||
// 1-based index를 0-based로 변환
|
||||
const todo = meetingTodos[index - 1];
|
||||
if (!todo) {
|
||||
showToast('Todo를 찾을 수 없습니다', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 모달에 데이터 채우기
|
||||
document.getElementById('editTodoId').value = index;
|
||||
document.getElementById('editTodoTitle').value = todo.title;
|
||||
|
||||
// 담당자 처리 (assignee가 객체인 경우 name 속성 사용)
|
||||
const assigneeName = typeof todo.assignee === 'object' ? todo.assignee.name : todo.assignee;
|
||||
document.getElementById('editTodoAssignee').value = assigneeName;
|
||||
|
||||
document.getElementById('editTodoDueDate').value = todo.dueDate;
|
||||
|
||||
// 회의 생성자 여부 확인
|
||||
const currentUser = '김민준'; // 현재 로그인 사용자
|
||||
const isCreator = checkIfUserIsCreator(CURRENT_MEETING_ID, currentUser);
|
||||
|
||||
// 담당자 필드 표시 여부 결정 (회의 생성자만 표시)
|
||||
const assigneeGroup = document.getElementById('editTodoAssigneeGroup');
|
||||
if (isCreator) {
|
||||
assigneeGroup.style.display = 'block';
|
||||
} else {
|
||||
assigneeGroup.style.display = 'none';
|
||||
}
|
||||
|
||||
// 모달 열기
|
||||
openModal('editTodoModal');
|
||||
}
|
||||
|
||||
/**
|
||||
* Todo 수정 저장 (index 기반)
|
||||
*/
|
||||
function saveTodoEdit() {
|
||||
const index = parseInt(document.getElementById('editTodoId').value);
|
||||
const title = document.getElementById('editTodoTitle').value.trim();
|
||||
const assignee = document.getElementById('editTodoAssignee').value.trim();
|
||||
const dueDate = document.getElementById('editTodoDueDate').value;
|
||||
|
||||
if (!title) {
|
||||
showToast('제목을 입력해주세요', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!assignee) {
|
||||
showToast('담당자를 입력해주세요', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!dueDate) {
|
||||
showToast('마감일을 선택해주세요', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
// 1-based index를 0-based로 변환하여 Todo 업데이트
|
||||
const todoIndex = index - 1;
|
||||
if (todoIndex >= 0 && todoIndex < meetingTodos.length) {
|
||||
const todo = meetingTodos[todoIndex];
|
||||
const oldAssignee = typeof todo.assignee === 'object' ? todo.assignee.name : todo.assignee;
|
||||
const oldDueDate = todo.dueDate;
|
||||
|
||||
// Todo 업데이트 (실제로는 API 호출)
|
||||
todo.title = title;
|
||||
|
||||
// assignee가 객체인 경우 name 속성만 업데이트
|
||||
if (typeof todo.assignee === 'object') {
|
||||
todo.assignee.name = assignee;
|
||||
} else {
|
||||
todo.assignee = assignee;
|
||||
}
|
||||
|
||||
todo.dueDate = dueDate;
|
||||
|
||||
showToast('Todo가 수정되었습니다', 'success');
|
||||
|
||||
// 담당자 변경 시 알림
|
||||
if (oldAssignee !== assignee) {
|
||||
setTimeout(() => {
|
||||
showToast(`${oldAssignee}와 ${assignee}에게 알림이 전송되었습니다`, 'info');
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// 마감일 변경 시 알림
|
||||
if (oldDueDate !== dueDate) {
|
||||
setTimeout(() => {
|
||||
showToast('캘린더가 업데이트되었습니다', 'info');
|
||||
}, oldAssignee !== assignee ? 2000 : 1000);
|
||||
}
|
||||
}
|
||||
|
||||
closeModal('editTodoModal');
|
||||
|
||||
// 페이지 새로고침 (실제로는 해당 Todo 항목만 업데이트)
|
||||
setTimeout(() => {
|
||||
location.reload();
|
||||
}, 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 페이지 초기화
|
||||
*/
|
||||
@@ -1740,13 +1863,19 @@
|
||||
const isCreator = checkIfUserIsCreator(CURRENT_MEETING_ID, currentUser);
|
||||
|
||||
if (isCreator) {
|
||||
const titleContainer = document.getElementById('meeting-title-container');
|
||||
const badge = titleContainer.querySelector('.badge');
|
||||
const badgesContainer = document.getElementById('meeting-badges');
|
||||
const crownIcon = document.createElement('span');
|
||||
crownIcon.textContent = '👑';
|
||||
crownIcon.style.fontSize = '24px';
|
||||
// badge 다음에 👑 삽입
|
||||
badge.insertAdjacentElement('afterend', crownIcon);
|
||||
crownIcon.style.fontSize = '20px';
|
||||
crownIcon.title = '회의 생성자';
|
||||
// 배지 영역에 크라운 추가
|
||||
badgesContainer.appendChild(crownIcon);
|
||||
} else {
|
||||
// 회의 생성자가 아닐 경우 creator-only 요소 숨김
|
||||
const creatorOnlyElements = document.querySelectorAll('.creator-only');
|
||||
creatorOnlyElements.forEach(element => {
|
||||
element.classList.add('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
updateTodoProgress();
|
||||
|
||||
@@ -6,6 +6,17 @@
|
||||
<title>회의록 수정 - 회의록 서비스</title>
|
||||
<link rel="stylesheet" href="common.css">
|
||||
<style>
|
||||
/*
|
||||
MVP 스코프 축소 v1.5.2 적용됨:
|
||||
- ❌ 실시간 협업 표시 ("편집 중" 표시 제거)
|
||||
- ❌ Todo 편집 기능 제거 (단순 조회만 가능)
|
||||
- ❌ 검증률 표시 및 최종 확정 버튼 제거
|
||||
- ✅ 안건별 검증 완료 체크박스 사용
|
||||
- ✅ Last Write Wins (LWW) 정책 적용
|
||||
- ✅ AI 요약 기능 통합: "AI 상세 요약" → "AI 요약"으로 명칭 변경
|
||||
- ✅ AI 재생성 버튼: 텍스트 편집 영역 내용 기반으로 한줄 요약 재생성
|
||||
*/
|
||||
|
||||
/* 페이지별 커스텀 스타일만 유지 */
|
||||
/* 공통 스타일(헤더, 메인콘텐츠, 안건, AI요약, 관련회의록, 액션바)은 common.css 사용 */
|
||||
|
||||
@@ -101,32 +112,8 @@
|
||||
gap: var(--space-xs);
|
||||
}
|
||||
|
||||
/* AI 한줄 요약 (읽기 전용, UFR-AI-036) */
|
||||
.ai-summary-oneline {
|
||||
background: var(--gray-50);
|
||||
border-left: 4px solid var(--primary);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-sm) var(--space-md);
|
||||
margin-bottom: var(--space-md);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
.ai-summary-oneline .lock-icon {
|
||||
font-size: 18px;
|
||||
color: var(--gray-500);
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.ai-summary-oneline .summary-text {
|
||||
font-size: var(--font-small);
|
||||
color: var(--gray-700);
|
||||
font-weight: var(--font-weight-medium);
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
/* AI 요약 편집 영역 (UFR-AI-036) */
|
||||
/* 헤더, textarea, footer 스타일은 common.css 사용 */
|
||||
/* AI 요약 편집 Footer (common.css에 없는 부분) */
|
||||
.ai-summary-footer {
|
||||
display: flex;
|
||||
@@ -187,6 +174,14 @@
|
||||
.reference-item {
|
||||
position: relative;
|
||||
padding-right: 40px; /* 삭제 버튼 공간 확보 */
|
||||
cursor: default; /* 카드 전체는 클릭 불가 */
|
||||
}
|
||||
|
||||
/* 수정 페이지에서는 카드 hover 효과 제거 (삭제 버튼만 클릭 가능) */
|
||||
.reference-item:hover {
|
||||
transform: none;
|
||||
border-color: var(--gray-200);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.remove-btn {
|
||||
@@ -245,6 +240,19 @@
|
||||
gap: var(--space-sm);
|
||||
}
|
||||
|
||||
/* 회의 생성자 전용 UI 표시 제어 */
|
||||
.creator-only {
|
||||
display: flex; /* 기본: 회의 생성자 환경 */
|
||||
}
|
||||
|
||||
.agenda-verification:not([data-is-creator="true"]) .creator-only {
|
||||
display: none; /* 참석자 환경에서는 숨김 */
|
||||
}
|
||||
|
||||
.agenda-verification:not(.verified) .creator-only {
|
||||
display: none; /* 검증 안 된 경우 버튼 숨김 */
|
||||
}
|
||||
|
||||
/* 읽기 전용 표시 */
|
||||
.readonly-badge {
|
||||
display: inline-flex;
|
||||
@@ -395,23 +403,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI 한줄 요약 (읽기 전용, UFR-AI-036) -->
|
||||
<div class="ai-summary-oneline">
|
||||
<span class="lock-icon">🔒</span>
|
||||
<span class="summary-text">타겟 고객을 20-30대로 설정, UI/UX 개선 집중</span>
|
||||
</div>
|
||||
|
||||
<!-- AI 상세 요약 편집 -->
|
||||
<!-- AI 요약 편집 (UFR-AI-036) -->
|
||||
<div class="ai-summary-edit">
|
||||
<div class="ai-summary-header">
|
||||
<span class="ai-summary-label">💡 AI 상세 요약</span>
|
||||
<button class="btn-secondary btn-sm" onclick="regenerateSummary(1)">AI 재생성</button>
|
||||
<span class="ai-summary-label">💡 AI 요약</span>
|
||||
<button class="btn btn-primary btn-sm" onclick="regenerateSummary(1)">AI 재생성</button>
|
||||
</div>
|
||||
<textarea
|
||||
class="ai-summary-textarea"
|
||||
placeholder="AI 요약을 입력하거나 수정하세요"
|
||||
readonly
|
||||
>신제품은 AI 기반 회의록 자동화 서비스로 결정. 타겟은 중소기업 및 스타트업이며, 주요 기능은 음성인식, AI 요약, Todo 추출입니다. 경쟁사 대비 차별점은 실시간 검증 및 협업 기능입니다.</textarea>
|
||||
>타겟 고객을 20-30대로 설정, UI/UX 개선 집중</textarea>
|
||||
<div class="ai-summary-footer">
|
||||
<span class="ai-summary-time">마지막 수정: 1시간 전</span>
|
||||
</div>
|
||||
@@ -466,16 +468,18 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 안건별 검증 (회의 생성자 권한) -->
|
||||
<div class="agenda-verification verified" id="verify-agenda-1">
|
||||
<!-- 안건별 검증 (UFR-COLLAB-030) -->
|
||||
<!-- 참석자: 체크박스만 표시 (검증완료 시 읽기 전용) -->
|
||||
<!-- 생성자: 검증완료 시 "잠금 해제" 버튼 표시 -->
|
||||
<div class="agenda-verification verified" id="verify-agenda-1" data-is-creator="true">
|
||||
<input type="checkbox" class="checkbox" id="verify-1" checked disabled>
|
||||
<div class="verification-label">
|
||||
<label for="verify-1">
|
||||
<span class="font-medium">검증 완료</span>
|
||||
<span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="verification-actions">
|
||||
<!-- 회의 생성자만 보이는 잠금 해제 버튼 (검증완료 시에만 표시) -->
|
||||
<div class="verification-actions creator-only">
|
||||
<button class="btn btn-secondary btn-sm" onclick="unlockAgendaVerification(1)">🔓 잠금 해제</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -492,23 +496,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI 한줄 요약 (읽기 전용, UFR-AI-036) -->
|
||||
<div class="ai-summary-oneline">
|
||||
<span class="lock-icon">🔒</span>
|
||||
<span class="summary-text">개발 기간 3개월, 백엔드 2명/프론트 2명/AI 1명 투입</span>
|
||||
</div>
|
||||
|
||||
<!-- AI 상세 요약 편집 -->
|
||||
<!-- AI 요약 편집 (UFR-AI-036) -->
|
||||
<div class="ai-summary-edit">
|
||||
<div class="ai-summary-header">
|
||||
<span class="ai-summary-label">💡 AI 상세 요약</span>
|
||||
<button class="btn-secondary btn-sm" onclick="regenerateSummary(2)">AI 재생성</button>
|
||||
<span class="ai-summary-label">💡 AI 요약</span>
|
||||
<button class="btn btn-primary btn-sm" onclick="regenerateSummary(2)">AI 재생성</button>
|
||||
</div>
|
||||
<textarea
|
||||
class="ai-summary-textarea"
|
||||
placeholder="AI 요약을 입력하거나 수정하세요"
|
||||
readonly
|
||||
>개발 기간은 3개월로 설정. 백엔드 2명, 프론트 2명, AI 엔지니어 1명 투입. 주간 스프린트로 진행하며, 2주마다 베타 테스트 실시.</textarea>
|
||||
>개발 기간 3개월, 백엔드 2명/프론트 2명/AI 1명 투입</textarea>
|
||||
<div class="ai-summary-footer">
|
||||
<span class="ai-summary-time">생성: 2025-10-25 16:32</span>
|
||||
</div>
|
||||
@@ -547,16 +545,18 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 안건별 검증 (회의 생성자 권한) -->
|
||||
<div class="agenda-verification verified" id="verify-agenda-2">
|
||||
<!-- 안건별 검증 (UFR-COLLAB-030) -->
|
||||
<!-- 참석자: 체크박스만 표시 (검증완료 시 읽기 전용) -->
|
||||
<!-- 생성자: 검증완료 시 "잠금 해제" 버튼 표시 -->
|
||||
<div class="agenda-verification verified" id="verify-agenda-2" data-is-creator="true">
|
||||
<input type="checkbox" class="checkbox" id="verify-2" checked disabled>
|
||||
<div class="verification-label">
|
||||
<label for="verify-2">
|
||||
<span class="font-medium">검증 완료</span>
|
||||
<span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="verification-actions">
|
||||
<!-- 회의 생성자만 보이는 잠금 해제 버튼 (검증완료 시에만 표시) -->
|
||||
<div class="verification-actions creator-only">
|
||||
<button class="btn btn-secondary btn-sm" onclick="unlockAgendaVerification(2)">🔓 잠금 해제</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -573,23 +573,17 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- AI 한줄 요약 (읽기 전용, UFR-AI-036) -->
|
||||
<div class="ai-summary-oneline">
|
||||
<span class="lock-icon">🔒</span>
|
||||
<span class="summary-text">프리 런칭 캠페인, LinkedIn 및 스타트업 커뮤니티 집중</span>
|
||||
</div>
|
||||
|
||||
<!-- AI 상세 요약 편집 -->
|
||||
<!-- AI 요약 편집 (UFR-AI-036) -->
|
||||
<div class="ai-summary-edit">
|
||||
<div class="ai-summary-header">
|
||||
<span class="ai-summary-label">💡 AI 상세 요약</span>
|
||||
<button class="btn-secondary btn-sm" onclick="regenerateSummary(3)">AI 재생성</button>
|
||||
<span class="ai-summary-label">💡 AI 요약</span>
|
||||
<button class="btn btn-primary btn-sm" onclick="regenerateSummary(3)">AI 재생성</button>
|
||||
</div>
|
||||
<textarea
|
||||
class="ai-summary-textarea"
|
||||
placeholder="AI 요약을 입력하거나 수정하세요"
|
||||
readonly
|
||||
>베타 출시 전 프리 런칭 캠페인 진행. 주요 채널은 LinkedIn 및 스타트업 커뮤니티. 초기 100팀 무료 제공 후 유료 전환 유도.</textarea>
|
||||
>프리 런칭 캠페인, LinkedIn 및 스타트업 커뮤니티 집중</textarea>
|
||||
<div class="ai-summary-footer">
|
||||
<span class="ai-summary-time">생성: 2025-10-25 16:35</span>
|
||||
</div>
|
||||
@@ -624,15 +618,15 @@
|
||||
</div>
|
||||
|
||||
<!-- 안건별 검증 (회의 생성자 권한) -->
|
||||
<div class="agenda-verification verified" id="verify-agenda-3">
|
||||
<div class="agenda-verification verified" id="verify-agenda-3" data-is-creator="true">
|
||||
<input type="checkbox" class="checkbox" id="verify-3" checked disabled>
|
||||
<div class="verification-label">
|
||||
<label for="verify-3">
|
||||
<span class="font-medium">검증 완료</span>
|
||||
<span class="text-caption text-muted"> (잠금됨 · 회의 생성자만 수정 가능)</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="verification-actions">
|
||||
<!-- 회의 생성자만 보이는 잠금 해제 버튼 (검증완료 시에만 표시) -->
|
||||
<div class="verification-actions creator-only">
|
||||
<button class="btn btn-secondary btn-sm" onclick="unlockAgendaVerification(3)">🔓 잠금 해제</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -743,12 +737,13 @@
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// AI 요약 재생성
|
||||
// AI 한줄 요약 재생성 (텍스트 편집 영역 내용 기반, UFR-AI-036)
|
||||
function regenerateSummary(agendaId) {
|
||||
showToast('AI 요약을 생성 중입니다...', 'info');
|
||||
showToast('AI 요약을 재생성 중입니다...', 'info');
|
||||
|
||||
setTimeout(() => {
|
||||
showToast('AI 요약이 생성되었습니다', 'success');
|
||||
showToast('재생성되었습니다', 'success');
|
||||
// 재생성된 한줄 요약은 회의록 상세조회 화면의 대시보드 및 회의록 탭에 즉시 반영됨
|
||||
markAsUnsaved();
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
@@ -453,10 +453,6 @@
|
||||
<span class="sidebar-nav-icon"><img src="img/edit.png" width="32"></span>
|
||||
<span>회의록</span>
|
||||
</a>
|
||||
<a href="09-Todo관리.html" class="sidebar-nav-item">
|
||||
<span class="sidebar-nav-icon"><img src="img/list.png" width="32"></span>
|
||||
<span>Todo 관리</span>
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<!-- 사용자 정보 영역 (Desktop) -->
|
||||
@@ -581,9 +577,6 @@
|
||||
<a href="12-회의록목록조회.html" class="nav-item active">
|
||||
<img src="img/edit.png" alt="회의록" style="width: 45px;">
|
||||
</a>
|
||||
<a href="09-Todo관리.html" class="nav-item">
|
||||
<img src="img/list.png" alt="Todo" style="width: 45px;">
|
||||
</a>
|
||||
</nav>
|
||||
|
||||
<script src="common.js"></script>
|
||||
|
||||
@@ -1429,11 +1429,12 @@ input[type="date"]::-webkit-calendar-picker-indicator {
|
||||
.related-meeting-item {
|
||||
background: var(--white);
|
||||
border-radius: var(--radius-md);
|
||||
padding: var(--space-sm);
|
||||
padding: var(--space-md);
|
||||
margin-bottom: var(--space-sm);
|
||||
display: flex;
|
||||
gap: var(--space-sm);
|
||||
transition: background var(--transition-fast);
|
||||
cursor: pointer;
|
||||
transition: all var(--transition-fast);
|
||||
border: 1px solid var(--gray-200);
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.reference-item:last-child,
|
||||
@@ -1443,7 +1444,15 @@ input[type="date"]::-webkit-calendar-picker-indicator {
|
||||
|
||||
.reference-item:hover,
|
||||
.related-meeting-item:hover {
|
||||
background: var(--gray-100);
|
||||
border-color: var(--primary);
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.12);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
.reference-item:active,
|
||||
.related-meeting-item:active {
|
||||
transform: translateY(0);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.reference-content,
|
||||
|
||||
Vendored
+9
-2
@@ -31,7 +31,7 @@ const SAMPLE_MEETINGS = [
|
||||
time: '14:00',
|
||||
duration: 90,
|
||||
location: '본사 2층 대회의실',
|
||||
status: 'scheduled', // ongoing, scheduled, completed
|
||||
status: 'draft', // ongoing, scheduled, completed, draft(작성중), complete(확정완료)
|
||||
participants: [
|
||||
{ id: 'user-001', name: '김민준', avatar: '김', avatarColor: 'green' },
|
||||
{ id: 'user-002', name: '박서연', avatar: '박', avatarColor: 'blue' },
|
||||
@@ -39,7 +39,8 @@ const SAMPLE_MEETINGS = [
|
||||
{ id: 'user-004', name: '최유진', avatar: '최', avatarColor: 'pink' }
|
||||
],
|
||||
sections: 3,
|
||||
todos: 5
|
||||
todos: 5,
|
||||
minutesId: 'minutes-001' // 회의록 ID 연결
|
||||
},
|
||||
{
|
||||
id: 'meeting-002',
|
||||
@@ -1083,6 +1084,12 @@ function getMeetingStatusInfo(meeting) {
|
||||
if (meeting.status === 'ongoing') {
|
||||
return { badgeType: 'ongoing', badgeText: '진행중' };
|
||||
}
|
||||
if (meeting.status === 'draft') {
|
||||
return { badgeType: 'draft', badgeText: '작성중' };
|
||||
}
|
||||
if (meeting.status === 'complete') {
|
||||
return { badgeType: 'complete', badgeText: '확정완료' };
|
||||
}
|
||||
if (meeting.status === 'completed') {
|
||||
return { badgeType: 'complete', badgeText: '확정완료' };
|
||||
}
|
||||
|
||||
@@ -1,5 +1,14 @@
|
||||
# 회의록 서비스 스타일 가이드
|
||||
|
||||
## 문서 정보
|
||||
- **작성일**: 2025-10-21
|
||||
- **최종 수정일**: 2025-10-27
|
||||
- **작성자**: 강지수 (Product Designer), 이미준 (서비스 기획자), 도그냥 (서비스 기획자)
|
||||
- **버전**: 1.3.1
|
||||
- **설계 철학**: Mobile First Design
|
||||
|
||||
---
|
||||
|
||||
## 1. 디자인 철학
|
||||
|
||||
### 핵심 원칙
|
||||
@@ -368,8 +377,10 @@
|
||||
- 02-대시보드: 최근 회의 카드, 내 회의록 카드
|
||||
- 10-회의록상세조회: 회의록 정보 섹션
|
||||
|
||||
### D-day 배지
|
||||
Todo 마감일 표시를 위한 D-day 배지 스타일입니다.
|
||||
### D-day 배지 (참고용)
|
||||
**⚠️ MVP 스코프 축소 (v1.3.1)**: D-day 배지는 09-Todo관리 화면에서만 사용됩니다. 10-회의록상세조회 및 11-회의록수정 화면에서는 Todo 단순 조회만 제공하므로 D-day 배지가 표시되지 않습니다.
|
||||
|
||||
Todo 마감일 표시를 위한 D-day 배지 스타일입니다 (09-Todo관리 화면 전용).
|
||||
|
||||
```css
|
||||
/* D-Day (오늘 마감) */
|
||||
@@ -1277,7 +1288,7 @@ Todo 마감일 표시를 위한 D-day 배지 스타일입니다.
|
||||
- 참석자 관리 (추가/삭제)
|
||||
- 회의록 최종 확정
|
||||
- 검증 완료된 안건 잠금 해제
|
||||
- 모든 Todo 수정 (담당자 변경 포함)
|
||||
- ~~모든 Todo 수정 (담당자 변경 포함)~~ **MVP 스코프 축소 (v1.3.1)**: Todo 편집 기능 제거
|
||||
- **사용 예시**:
|
||||
- "회의 생성자 전용 기능"
|
||||
- "회의 생성자만 회의를 종료할 수 있습니다"
|
||||
@@ -1288,11 +1299,11 @@ Todo 마감일 표시를 위한 D-day 배지 스타일입니다.
|
||||
- 회의록 조회
|
||||
- 안건 편집 (검증 완료 전)
|
||||
- 안건 검증
|
||||
- 본인의 Todo 수정 (담당자 변경 불가)
|
||||
- ~~본인의 Todo 수정 (담당자 변경 불가)~~ **MVP 스코프 축소 (v1.3.1)**: Todo 편집 기능 제거, 단순 조회만 가능
|
||||
- 회의록 목록 조회 (본인이 참석한 회의만)
|
||||
- **사용 예시**:
|
||||
- "모든 참석자가 편집할 수 있습니다"
|
||||
- "참석자는 본인의 Todo만 수정 가능합니다"
|
||||
- ~~"참석자는 본인의 Todo만 수정 가능합니다"~~ **변경 (v1.3.1)**: "Todo는 조회만 가능합니다"
|
||||
|
||||
### 사용하지 않는 용어
|
||||
- ❌ "회의록 작성자" - 명확하지 않으므로 사용 금지
|
||||
@@ -1304,6 +1315,8 @@ Todo 마감일 표시를 위한 D-day 배지 스타일입니다.
|
||||
|
||||
| 버전 | 날짜 | 작성자 | 변경 내용 |
|
||||
|------|------|--------|----------|
|
||||
| 1.3.1 | 2025-10-27 | 강지수 | MVP 스코프 축소 v2.4.0 반영 (Todo 관련 섹션 수정)<br>- **D-day 배지 섹션**: 참고용으로 변경, 09-Todo관리 화면에서만 사용됨을 명시<br> - 10-회의록상세조회 및 11-회의록수정 화면에서는 Todo 단순 조회만 제공<br>- **사용자 역할 용어**: 권한 설명 업데이트<br> - 회의 생성자: "모든 Todo 수정" 권한 제거됨 (취소선 표시)<br> - 회의 참석자: "본인의 Todo 수정" 권한 제거됨 (취소선 표시)<br> - Todo는 조회만 가능하도록 변경<br>- **일관성 유지**: UI/UX 설계서 v1.5.1과 동기화 |
|
||||
| 1.3.0 | 2025-10-24 | 이미준 | 사용자 역할 용어 통일 (유저스토리 v2.1.2 반영)<br>- **용어 정의 섹션 추가**: "회의 생성자"와 "회의 참석자" 용어 명확히 정의<br> - 회의 생성자: 회의 예약을 생성한 사용자, 회의 시작/종료/최종 확정 권한<br> - 회의 참석자: 회의에 참석하는 모든 사용자 (생성자 포함), 회의록 편집/조회 권한<br>- **사용하지 않는 용어 명시**: "회의록 작성자", "작성자" 용어 사용 금지<br>- **권한 상세 설명**: 생성자 전용 기능, 참석자 공통 기능 구체화<br>- **일관성 달성**: 유저스토리, 화면설계서, 스타일 가이드 간 용어 완전 통일 |
|
||||
| 1.0 | 2025-10-21 | 최유진 | 최초 작성 - reference/sampleimg 샘플 이미지 기반 스타일 가이드 작성 |
|
||||
| 1.0.1 | 2025-10-21 | 이미준 | 네비게이션 간소화 및 인터랙션 개선<br>- 설정 메뉴를 프로필 메뉴로 통합 (사이드바, 하단 네비게이션)<br>- 로그아웃 및 개인 설정 기능은 프로필 영역에서 접근<br>- Todo 항목 클릭 시 회의록 상세 화면으로 이동하는 인터랙션 추가<br>- 네비게이션 메뉴 항목: 대시보드, 회의 목록, Todo 관리, 프로필 (4개 항목) |
|
||||
| 1.1 | 2025-10-21 | 이미준 | 반응형 네비게이션 및 2열 레이아웃 패턴 추가<br>- **반응형 네비게이션 전략**: Mobile (하단 네비게이션), Desktop (왼쪽 사이드바 240px)<br>- **사이드바 네비게이션 (Desktop)**: 로고 영역, 메뉴 항목 (대시보드/회의 목록/Todo 관리), 사용자 정보 영역<br>- **하단 네비게이션 (Mobile)**: 홈/회의록/Todo/프로필 (4개 메뉴)<br>- **2열 레이아웃 패턴**: 회의 진행 화면용 (왼쪽 65% 에디터, 오른쪽 35% 탭 패널)<br>- **탭 네비게이션 사용 예시**: 회의록 상세 (2개 탭), 회의 진행 (4개 탭) |
|
||||
|
||||
+312
-224
@@ -2,25 +2,60 @@
|
||||
|
||||
## 문서 정보
|
||||
- **작성일**: 2025-10-21
|
||||
- **최종 수정일**: 2025-10-25
|
||||
- **최종 수정일**: 2025-10-27
|
||||
- **작성자**: 이미준 (서비스 기획자)
|
||||
- **버전**: 1.4.20
|
||||
- **버전**: 1.5.3
|
||||
- **설계 철학**: Mobile First Design
|
||||
|
||||
---
|
||||
|
||||
## 목차
|
||||
1. [설계 개요](#설계-개요)
|
||||
- [설계 목표](#설계-목표)
|
||||
- [설계 원칙](#설계-원칙)
|
||||
- [유저스토리 매핑](#유저스토리-매핑)
|
||||
- [주요 추가 기능 (v1.1)](#주요-추가-기능-v11)
|
||||
2. [프로토타입 화면 목록](#프로토타입-화면-목록)
|
||||
3. [화면 간 사용자 플로우](#화면-간-사용자-플로우)
|
||||
- [주요 사용자 시나리오별 플로우](#주요-사용자-시나리오별-플로우)
|
||||
- [플로우 다이어그램](#플로우-다이어그램)
|
||||
4. [화면별 상세 설계](#화면별-상세-설계)
|
||||
- [01-로그인](#01-로그인)
|
||||
- [02-대시보드](#02-대시보드)
|
||||
- [03-회의예약](#03-회의예약)
|
||||
- [04-템플릿선택](#04-템플릿선택)
|
||||
- [05-회의진행](#05-회의진행)
|
||||
- [07-회의종료](#07-회의종료)
|
||||
- [09-Todo관리](#09-todo관리)
|
||||
- [10-회의록상세조회](#10-회의록상세조회)
|
||||
- [11-회의록수정](#11-회의록수정)
|
||||
- [12-회의록목록조회](#12-회의록목록조회)
|
||||
5. [공통 UI 컴포넌트](#공통-ui-컴포넌트)
|
||||
6. [공통 에러 메시지 표준](#공통-에러-메시지-표준)
|
||||
- [네트워크 오류](#네트워크-오류)
|
||||
- [데이터 로딩 실패](#데이터-로딩-실패)
|
||||
- [권한 오류](#권한-오류)
|
||||
- [인증 오류](#인증-오류)
|
||||
- [입력 검증 오류](#입력-검증-오류)
|
||||
- [서버 오류](#서버-오류)
|
||||
7. [화면 간 전환 및 네비게이션](#화면-간-전환-및-네비게이션)
|
||||
8. [반응형 설계 전략](#반응형-설계-전략)
|
||||
- [브레이크포인트](#브레이크포인트)
|
||||
- [레이아웃 전략](#레이아웃-전략)
|
||||
- [컴포넌트별 반응형 전략](#컴포넌트별-반응형-전략)
|
||||
- [이미지 및 미디어](#이미지-및-미디어)
|
||||
9. [접근성 보장 방안](#접근성-보장-방안)
|
||||
10. [성능 최적화 방안](#성능-최적화-방안)
|
||||
- [1. 로딩 성능](#1-로딩-성능)
|
||||
- [2. 렌더링 성능](#2-렌더링-성능)
|
||||
- [3. 네트워크 최적화](#3-네트워크-최적화)
|
||||
- [4. 실시간 동기화 최적화](#4-실시간-동기화-최적화)
|
||||
- [5. 성능 모니터링](#5-성능-모니터링)
|
||||
- [성능 목표](#성능-목표)
|
||||
11. [변경 이력](#변경-이력)
|
||||
12. [부록](#부록)
|
||||
- [참고 자료](#참고-자료)
|
||||
- [디자인 시스템 (추후 작성)](#디자인-시스템-추후-작성)
|
||||
|
||||
---
|
||||
|
||||
@@ -72,14 +107,16 @@
|
||||
- 관련도 표시 (퍼센트 또는 별점)
|
||||
- 최대 3개 자동 표시, 더보기로 전체 목록 확인 가능
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 프로토타입 화면 목록
|
||||
|
||||
| 번호 | 화면명 | 관련 유저스토리 | 비즈니스 중요도 | 사이드바 유무 | 이전화면 이동버튼 유무 | 비고 |
|
||||
|------|--------|----------------|-------------------|-----------|------------------------|-------|
|
||||
| 01 | 로그인 | UFR-USER-010 | 필수 | 사용자 인증 | X | X | |
|
||||
| 02 | 대시보드 | - | 필수 | 메인 랜딩 페이지 | O | X | |
|
||||
| 번호 | 화면명 | 관련 유저스토리 | 비즈니스 중요도 | 설명 | 사이드바 유무 | 이전화면 이동버튼 유무 | 비고 |
|
||||
|------|--------|----------------|-------------------|------------------------|------------|------------------------|-------|
|
||||
| 01 | 로그인 | UFR-USER-010 | 필수 | 사용자 인증 | X | X | |
|
||||
| 02 | 대시보드 | UFR-USER-020 | 필수 | 메인 랜딩 페이지 | O | X | |
|
||||
| 03 | 회의예약 | UFR-MEET-010 | 높음 | 회의 생성 | X | O | |
|
||||
| 04 | 템플릿선택 | UFR-MEET-020 | 중간 | 회의록 템플릿 선택 | X | O | |
|
||||
| 05 | 회의진행 | UFR-MEET-030, UFR-STT-010/020, UFR-AI-010, UFR-COLLAB-010 | 높음 | 실시간 회의 진행 및 회의록 작성 | X | X | |
|
||||
@@ -87,7 +124,9 @@
|
||||
| 09 | Todo관리 | UFR-TODO-010, UFR-TODO-030 | 높음 | Todo 목록 및 진행 관리 | O | X | |
|
||||
| 10 | 회의록상세조회 | UFR-MEET-047 | 중간 | 회의록 상세 보기 | X | O | |
|
||||
| 11 | 회의록수정 | UFR-MEET-055 | 중간 | 지난 회의록 수정 | X | O | |
|
||||
| 12 | 회의록목록조회 | UFR-MEET-046 | 높음 | 회의록 목록 필터링/정렬/검색 | O | X | |
|
||||
| 12 | 회의록목록조회 | UFR-MEET-046 | 높음 | 회의록 목록 필터링/정렬/검색 | O | X | |
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
@@ -143,6 +182,8 @@ graph TD
|
||||
E -.실시간 연동.-> L
|
||||
```
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 화면별 상세 설계
|
||||
@@ -207,20 +248,25 @@ graph TD
|
||||
### 02-대시보드
|
||||
|
||||
#### 개요
|
||||
- **목적**: 주요 기능 접근 허브, 최근 활동 및 Todo 요약 제공
|
||||
- **관련 유저스토리**: 여러 유저스토리의 진입점, UFR-MEET-030 (회의록 조회), UFR-TODO-010 (Todo 조회)
|
||||
- **목적**: 주요 기능 접근 허브, 최근 활동 요약 제공
|
||||
- **관련 유저스토리**: UFR-USER-020 (대시보드 조회)
|
||||
- **비즈니스 중요도**: 필수
|
||||
- **접근 경로**: 로그인 후 메인 화면
|
||||
|
||||
#### 주요 기능
|
||||
#### 주요 기능 (MVP 스코프 축소 v1.5.0)
|
||||
1. 빠른 회의 시작 및 예약
|
||||
2. **예정된/진행중 회의 목록** (upcoming & ongoing meetings)
|
||||
- 예정된 회의 (아직 시작 전)
|
||||
- 진행중 회의 (참여 가능한 회의)
|
||||
3. **내 Todo 우선순위별 표시** (지연중 → 진행중 → 미진행 → 완료, 최대 5개)
|
||||
4. **내 회의록** (참여자/생성자로 등록된 최근 3개, 상태 포함)
|
||||
3. **통계 정보 표시** (예정된 회의, 작성중 회의록)
|
||||
4. **내 회의록** (참여자/생성자로 등록된 최근 4개, 상태 포함)
|
||||
5. 전역 검색
|
||||
|
||||
**변경사항 (v1.5.0)**:
|
||||
- ❌ 제거: "내 Todo" 섹션 및 Todo 관리 메뉴
|
||||
- ✅ 추가: "작성중 회의록" 통계 카드
|
||||
- ✅ 변경: 네비게이션 간소화 (대시보드, 회의록만 유지)
|
||||
|
||||
#### UI 구성요소
|
||||
|
||||
**Mobile (320px~768px)**
|
||||
@@ -231,14 +277,15 @@ graph TD
|
||||
- 예정된 회의가 없을 경우: "예정된 회의가 없습니다"
|
||||
|
||||
- **메인 콘텐츠** (스크롤, padding-bottom: 80px, background: gray-50)
|
||||
- **통계 카드 컴팩트 배치** (단일 카드) - **개선안 A 적용 (v1.5)**
|
||||
- 제목: "📊 오늘의 현황" (H5, Semibold)
|
||||
- 수평 배치 (flex, space-around):
|
||||
- "📅 예정 {N}" (Icon + Label + Value)
|
||||
- "✅진행 {N}" (Icon + Label + Value)
|
||||
- "📈 완료 {N}%" (Icon + Label + Value)
|
||||
- 높이: ~80px (기존 대비 70% 감소)
|
||||
- 반응형: 태블릿 이상에서 justify-content: flex-start, gap 증가
|
||||
- **통계 카드** (2열 그리드) - **v1.5.0 변경**
|
||||
- "📅 예정된 회의" 카드
|
||||
- 값: 전체 예정 + 진행 중 회의 개수
|
||||
- 클릭 액션: 없음 (정보 표시만)
|
||||
- "📝 작성중 회의록" 카드
|
||||
- 값: 내가 참석한 회의 중 '작성중' 상태인 회의록 개수
|
||||
- 클릭 액션: 없음 (정보 표시만)
|
||||
- 높이: ~80px
|
||||
- 반응형: 태블릿 이상에서 간격 증가
|
||||
|
||||
- **최근 회의** 섹션
|
||||
- 헤더: "예정된 회의" (H4) + "전체 보기 →" 링크
|
||||
@@ -270,26 +317,9 @@ graph TD
|
||||
- 타이머 표시: "10분 후 참여 가능" (시작 시간까지 남은 시간)
|
||||
- 빈 상태: "예정된 회의가 없습니다"
|
||||
|
||||
- **내 Todo** 카드 (개선)
|
||||
- 헤더: "내 Todo" (H4) + "전체 보기 →" 링크 (Todo 관리 화면으로 이동)
|
||||
- **통계 요약 영역**:
|
||||
- 진행 중 개수 배지
|
||||
- 마감 임박 개수 (아이콘: schedule, 경고색)
|
||||
- **Todo 리스트** (우선순위 순, 최대 5개):
|
||||
1. 지연 중 (기한 지남, 빨간색)
|
||||
2. 진행 중 (상태: in_progress)
|
||||
3. 기한이 남은 미진행 (상태: not_started)
|
||||
4. 완료 (상태: done, 회색 처리)
|
||||
- 각 Todo 항목:
|
||||
- 제목 (Medium weight)
|
||||
- 메타정보: 담당자, 마감일
|
||||
- D-day (색상: 지남-빨강, 오늘-경고, 여유-회색)
|
||||
- 우선순위 배지 (high-빨강, medium-노랑, low-회색)
|
||||
- 빈 상태: "할당된 Todo가 없습니다"
|
||||
|
||||
- **내 회의록** 카드 (개선)
|
||||
- **내 회의록** 카드 - **v1.5.0 변경 (Todo 섹션 제거)**
|
||||
- 헤더: "내 회의록" (H4) + "전체 보기 →" 링크 (회의록 목록 화면으로 이동)
|
||||
- **최근 회의록 리스트** (최대 3개):
|
||||
- **최근 회의록 리스트** (최대 4개, 2x2 그리드):
|
||||
- 필터: 내가 참여자 또는 생성자로 등록된 회의록
|
||||
- 정렬: 최근 생성 순 (createdAt 기준)
|
||||
- 각 항목:
|
||||
@@ -297,14 +327,16 @@ graph TD
|
||||
- 회의 일시 (날짜 + 시간)
|
||||
- 참석자 수
|
||||
- **상태 배지**:
|
||||
- "작성중" (draft, 노란색 배지)
|
||||
- "작성중" (draft, 주황색 배지)
|
||||
- "확정완료" (confirmed, 초록색 배지)
|
||||
- 최종 수정 시간 (상대 시간: "1시간 전", "어제" 등)
|
||||
- 검증완료율 표시 (작성중인 경우만)
|
||||
- 클릭 시: 회의록 상세 화면으로 이동
|
||||
- 빈 상태: "작성한 회의록이 없습니다. 첫 회의를 시작해보세요!"
|
||||
- 빈 상태: "참여한 회의록이 없습니다"
|
||||
|
||||
**Mobile (320px~768px)**
|
||||
- **하단 네비게이션**: [Mobile 하단 네비게이션](#mobile-하단-네비게이션-320px768px) 참조 (홈 활성)
|
||||
**Mobile (320px~768px)** - **v1.5.0 네비게이션 간소화**
|
||||
- **하단 네비게이션**: 2개 메뉴만 표시
|
||||
- 홈 (대시보드) - 활성 상태
|
||||
- 회의록 (회의록 목록)
|
||||
|
||||
**Tablet/Desktop (768px+)**
|
||||
- **좌측 사이드바**: [Desktop 좌측 사이드바](#desktop-좌측-사이드바-768px) 참조 (대시보드 활성)
|
||||
@@ -314,22 +346,17 @@ graph TD
|
||||
- "안녕하세요, {사용자명}님!" (H2)
|
||||
- "오늘의 일정을 확인하세요" (부제)
|
||||
|
||||
- **통계 카드 그리드** (3개, auto-fit)
|
||||
- **통계 카드 그리드** (2개) - **v1.5.0 변경**
|
||||
- 예정된 회의 (📅)
|
||||
- 진행 중 Todo (✅)
|
||||
- Todo 완료율 (📈)
|
||||
- 작성중 회의록 (📝)
|
||||
|
||||
- **최근 회의 그리드** (2-3컬럼)
|
||||
- 회의 카드들 (진행중 우선)
|
||||
- 참여하기/수정/보기 버튼
|
||||
|
||||
- **할당된 Todo 리스트**
|
||||
- 화이트 카드 배경
|
||||
- 각 Todo 항목 구분선
|
||||
|
||||
- **내 회의록 리스트**
|
||||
- 화이트 카드 배경
|
||||
- 전체보기 → 11-회의록목록조회.html
|
||||
- 전체보기 → 12-회의록목록조회.html
|
||||
|
||||
- **하단 네비게이션**: 숨김 (데스크톱에서는 사이드바 사용)
|
||||
|
||||
@@ -628,22 +655,27 @@ graph TD
|
||||
|
||||
#### 개요
|
||||
- **목적**: 실시간 회의 진행 및 AI 기반 회의록 자동 작성
|
||||
- **관련 유저스토리**: UFR-MEET-030, UFR-STT-010/020, UFR-AI-010, UFR-AI-040, UFR-COLLAB-010, UFR-RAG-010/020, UFR-PART-010/020/030, UFR-HOST-010/020, UFR-TERM-010/020
|
||||
- **관련 유저스토리**: UFR-MEET-030, UFR-STT-010/020, UFR-AI-010, UFR-AI-040, UFR-COLLAB-010, UFR-RAG-010/020, UFR-PART-020, UFR-HOST-010/020, UFR-TERM-010/020
|
||||
- **비즈니스 중요도**: 높음 (핵심 화면)
|
||||
- **접근 경로**: 대시보드 → "참여하기" 버튼 (페이지 전환)
|
||||
- **권한** (MVP 개선):
|
||||
- **회의 생성자 전용**: 회의 종료, 녹음 제어 (일시정지/재개/종료)
|
||||
- **모든 참석자**: 회의 참여, AI 주요 내용 체크, 용어 확인, 관련 회의록 확인, 중도 퇴장
|
||||
- **모든 참석자**: 회의 참여, AI 기반 메모 작성, 용어 확인, 관련 회의록 확인, 중도 퇴장
|
||||
|
||||
#### 주요 기능
|
||||
#### 주요 기능 (MVP 스코프 축소 v1.5.0)
|
||||
1. 음성 녹음 및 실시간 텍스트 변환 (STT)
|
||||
2. AI 자동 회의록 작성 (구조화)
|
||||
3. **AI 기반 주요 메모 항목 실시간 제안** (UFR-MEET-030)
|
||||
3. **AI 기반 메모 작성** (UFR-PART-020): AI가 실시간으로 감지한 주요 내용을 참석자가 선택하여 개인 메모로 저장
|
||||
4. 전문용어 자동 감지 및 맥락 기반 설명
|
||||
5. **참고자료 자동 연결** (이전 회의록, 관련 회의록)
|
||||
6. 참석자 관리 및 초대 기능
|
||||
7. 회의 진행 시간 표시
|
||||
|
||||
**변경사항 (v1.5.0)**:
|
||||
- ✅ 변경: "AI 제안" 탭 → "AI 기반 메모" 탭으로 기능 변경
|
||||
- ✅ 추가: 개인 메모 입력 및 저장 기능 (각 참석자별 개별 저장)
|
||||
- ✅ 정책: 메모는 회의 종료 전까지만 표시/편집 가능, 다른 참석자 메모는 볼 수 없음
|
||||
|
||||
#### UI 구성요소
|
||||
|
||||
**전체 레이아웃**
|
||||
@@ -654,7 +686,7 @@ graph TD
|
||||
- **메인 콘텐츠 영역: 정보 패널** (탭 구조)
|
||||
- **탭 네비게이션** (4개 탭)
|
||||
- 참석자 (3명)
|
||||
- AI 제안
|
||||
- AI 기반 메모
|
||||
- 용어 사전
|
||||
- 관련 자료 (32건)
|
||||
|
||||
@@ -676,17 +708,69 @@ graph TD
|
||||
- flex layout, 하단 구분선 (마지막 제외)
|
||||
- 상태 표시 제거됨 (발언 중/온라인 등 표시 안 함)
|
||||
|
||||
- **AI 제안 탭**
|
||||
- 제목: "AI 제안"
|
||||
- **카드 디자인** (통일된 스타일):
|
||||
- 배경: 연한 회색 (#FAFAFA)
|
||||
- 테두리: 회색 점선 (1px dashed #D0D0D0)
|
||||
- 테두리 둥글기: 8px
|
||||
- 내부 패딩: 16px
|
||||
- 카드 간 여백: 16px
|
||||
- 헤더 폰트: 16px Bold, 민트 그린 (#4DD5A7)
|
||||
- 본문 폰트: 14px, gray-700
|
||||
- 구조: 헤더 + 본문 텍스트 + 액션 버튼
|
||||
- **AI 기반 메모 탭** (UFR-PART-020)
|
||||
- 제목: "AI 기반 메모"
|
||||
|
||||
- **메모 입력 영역** (상단):
|
||||
- **메모 입력 텍스트박스**:
|
||||
- placeholder: "메모를 입력하세요..."
|
||||
- 다중 행 입력 지원 (textarea)
|
||||
- 배경: 화이트 (#FFFFFF)
|
||||
- 테두리: 회색 실선 (1px solid #E5E7EB)
|
||||
- 테두리 둥글기: 8px
|
||||
- 내부 패딩: 12px
|
||||
- 최소 높이: 80px
|
||||
- **저장 버튼**:
|
||||
- 텍스트: "저장"
|
||||
- 스타일: btn btn-primary (민트 그린)
|
||||
- 위치: 메모 입력창 하단 우측
|
||||
- 여백: 상단 8px
|
||||
- **구분선**:
|
||||
- 메모 입력 영역 하단에 회색 구분선 (1px solid #E5E7EB)
|
||||
- 상하 여백: 16px
|
||||
|
||||
- **AI가 감지한 주요 내용 영역** (하단):
|
||||
- **섹션 헤더**:
|
||||
- 텍스트: "AI가 감지한 주요 내용"
|
||||
- 폰트: 16px Bold, gray-800
|
||||
- 하단 여백: 12px
|
||||
|
||||
- **주요 내용 리스트**:
|
||||
- **리스트 아이템 디자인**:
|
||||
- 배경: 연한 회색 (#FAFAFA)
|
||||
- 테두리: 회색 점선 (1px dashed #D0D0D0)
|
||||
- 테두리 둥글기: 8px
|
||||
- 내부 패딩: 12px
|
||||
- 아이템 간 여백: 8px
|
||||
- 호버 시: 민트 그린 배경 (#E8F9F3), 커서 포인터
|
||||
|
||||
- **아이템 구조**:
|
||||
- 시간 태그 (좌측):
|
||||
- 형식: "[HH:MM]"
|
||||
- 폰트: 12px Bold, 민트 그린 (#4DD5A7)
|
||||
- 배경: 민트 그린 연한 배경 (#E8F9F3)
|
||||
- 패딩: 4px 8px
|
||||
- 테두리 둥글기: 4px
|
||||
- 주요 내용 텍스트 (우측):
|
||||
- 폰트: 14px, gray-700
|
||||
- flex-grow: 1
|
||||
- 좌측 여백: 8px
|
||||
|
||||
- **아이템 예시**:
|
||||
- `[15:32] 예산 책정 관련 결정`
|
||||
- `[15:35] 다음 회의 일정 합의`
|
||||
- `[15:38] API 설계 패턴 논의`
|
||||
- `[15:42] 마이크로서비스 아키텍처 채택`
|
||||
|
||||
- **클릭 인터랙션**:
|
||||
- 아이템 클릭 시 → 메모 입력창에 "[시간] 내용" 형식으로 자동 추가
|
||||
- 기존 메모가 있으면 줄바꿈 후 추가
|
||||
- 입력된 메모는 수정 가능
|
||||
|
||||
- **정책**:
|
||||
- 각 참석자별로 개별 저장 (다른 참석자의 메모는 볼 수 없음)
|
||||
- 메모는 회의 종료 전까지만 표시 및 편집 가능
|
||||
- 회의 종료 시 AI가 회의록 생성할 때 모든 참석자의 메모 참조
|
||||
|
||||
- **용어 사전 탭**
|
||||
- 제목: "용어 사전"
|
||||
@@ -792,15 +876,26 @@ graph TD
|
||||
- 상태 표시 없음 (발언 중/온라인 등 제거)
|
||||
- 참석자 수 동적 업데이트 (초대 성공 시)
|
||||
|
||||
- **AI 제안 탭**: AI가 생성한 주요 메모 항목 제안 (UFR-MEET-030)
|
||||
- **실시간 주요 메모 추천**:
|
||||
- **AI 기반 메모 탭** (UFR-PART-020): AI가 감지한 주요 내용을 참석자가 선택하여 개인 메모로 저장
|
||||
- **메모 작성 및 저장**:
|
||||
- 메모 입력창에 자유롭게 메모 작성 가능
|
||||
- "저장" 버튼 클릭 시 개인 메모로 저장 (각 참석자별 개별 저장)
|
||||
- 저장 성공 시 "{n}개의 메모가 저장되었습니다" 성공 토스트
|
||||
- 저장 실패 시 "메모 저장에 실패했습니다" 오류 토스트
|
||||
- **AI가 감지한 주요 내용**:
|
||||
- 음성→텍스트 변환 후 AI가 실시간으로 회의 내용 분석
|
||||
- **중요한 내용으로 판단된 경우에만** 주요 메모 항목 제안
|
||||
- 논의항목/결정사항 등의 구분 없이 중요 내용을 주요 메모로 제안
|
||||
- 추천 빈도는 중요 내용 발생에 따라 가변적 (고정 간격 아님)
|
||||
- 각 제안 항목에 "주요 메모에 추가" 버튼 제공
|
||||
- 클릭 시 해당 안건의 주요 메모에 자동 저장
|
||||
- 실시간 업데이트: 새로운 제안은 상단에 표시
|
||||
- **중요한 내용으로 판단된 경우에만** 주요 내용 항목 표시
|
||||
- 각 항목: "[시간] 주요 내용 텍스트" 형식 (예: "[15:32] 예산 책정 관련 결정")
|
||||
- 실시간 업데이트: 새로운 항목은 하단에 추가
|
||||
- 항목 클릭 시:
|
||||
1. 메모 입력창에 "[시간] 내용" 형식으로 자동 추가
|
||||
2. 기존 메모가 있으면 줄바꿈 후 추가
|
||||
3. 입력된 메모는 수정 가능 (자동/수동 구분 표시)
|
||||
4. 저장 버튼 활성화
|
||||
- **정책**:
|
||||
- 메모는 회의 종료 전까지만 표시/편집 가능
|
||||
- 각 참석자의 메모는 다른 참석자에게 보이지 않음
|
||||
- 회의 종료 시 AI가 모든 참석자의 메모를 참조하여 회의록 생성
|
||||
|
||||
- **용어 사전 탭**: 회의에서 언급된 전문용어 설명
|
||||
- **용어 검색 기능**:
|
||||
@@ -840,24 +935,25 @@ graph TD
|
||||
- 참석자 초대 이메일
|
||||
- **출력**:
|
||||
- 실시간 텍스트 변환 결과 (STT)
|
||||
- **AI 제안 목록** (주요 메모 항목 제안)
|
||||
- **AI가 감지한 주요 내용 목록** (시간 + 내용)
|
||||
- **개인 메모** (각 참석자별 개별 저장)
|
||||
- **전문용어 및 설명** (용어 사전)
|
||||
- **관련 회의록 목록** (32건, 관련도 포함)
|
||||
- 참석자 목록
|
||||
- **연동**:
|
||||
- STT 서비스 (UFR-AI-010)
|
||||
- AI 서비스 (주요 메모 제안 생성, UFR-AI-040)
|
||||
- AI 서비스 (주요 내용 감지, UFR-AI-040)
|
||||
- RAG 서비스 (관련 회의록 검색, 전문용어 자동 감지)
|
||||
- Collaboration 서비스 (실시간 동기화)
|
||||
- PARTICIPANT 서비스 (메모 저장, UFR-PART-020)
|
||||
|
||||
#### 에러 처리
|
||||
- **마이크 권한 거부**: "마이크 권한이 필요합니다" 토스트 + 설정 안내 링크
|
||||
- **STT 실패**: "음성 인식에 실패했습니다" 토스트 + 재시도 안내
|
||||
- **AI 제안 생성 실패**: "AI 제안을 불러올 수 없습니다" 토스트
|
||||
- **AI 주요 내용 감지 실패**: "AI 주요 내용 감지에 실패했습니다" 토스트 (회의 계속 진행 가능)
|
||||
- **메모 저장 실패**: "메모 저장에 실패했습니다" 토스트 + 재시도 버튼
|
||||
- **용어 사전 로드 실패**: "용어 사전을 불러올 수 없습니다" 메시지 표시
|
||||
- **관련 자료 검색 실패**: "관련 회의록을 찾을 수 없습니다" 메시지 표시
|
||||
- **참석자 초대 실패**: "초대 링크 전송에 실패했습니다" 토스트 + 재시도 버튼
|
||||
- **동기화 실패**: "네트워크 연결을 확인해주세요" 토스트
|
||||
- **회의 종료 실패**: "회의 종료 중 오류가 발생했습니다" 토스트 + 재시도 버튼
|
||||
|
||||
---
|
||||
@@ -1157,27 +1253,34 @@ graph TD
|
||||
|
||||
#### 개요
|
||||
- **목적**: 지난 회의록의 전체 내용 및 상세 정보 확인
|
||||
- **관련 유저스토리**: UFR-MEET-047, UFR-AI-040
|
||||
- **관련 유저스토리**: UFR-MEET-047, UFR-AI-040, UFR-MEET-048
|
||||
- **비즈니스 중요도**: 중간
|
||||
- **접근 경로**: 대시보드 → "내 회의록" 항목 클릭 또는 Todo관리 → 회의록 링크
|
||||
- **접근 경로**: 대시보드 → "내 회의록" 항목 클릭
|
||||
- **권한**: 모든 회의 참석자 (조회 전용)
|
||||
|
||||
#### 주요 기능
|
||||
#### 주요 기능 (MVP 스코프 축소 v1.5.0)
|
||||
1. 회의 기본 정보 표시
|
||||
2. **안건별 AI 요약 표시** (안건 최상단)
|
||||
3. 안건별 상세 내용 표시
|
||||
4. **참고자료 표시** (안건 하단)
|
||||
5. Todo 항목 및 진행 상황 표시
|
||||
5. **Todo 단순 조회** (UFR-MEET-047): 제목, 담당자만 표시 (D-day, 우선순위 라벨 제거)
|
||||
6. 첨부파일 다운로드
|
||||
7. 회의록 수정/공유 액션
|
||||
|
||||
**변경사항 (v1.5.0)**:
|
||||
- ❌ 제거: Todo 관리 화면 연동 링크 (화면 자체가 제거됨)
|
||||
- ❌ 제거: Todo D-day 라벨, 우선순위 배지 표시
|
||||
- ✅ 변경: Todo는 단순 조회만 가능 (제목 + 담당자 + 마감일만 표시)
|
||||
- ✅ 변경: "수정" 버튼을 회의 제목 우측으로 이동
|
||||
|
||||
#### UI 구성요소
|
||||
|
||||
**Mobile (320px~768px)**
|
||||
- **헤더**
|
||||
- 뒤로가기 버튼
|
||||
- 회의 제목
|
||||
- 메뉴 버튼 (수정, 삭제)
|
||||
- "수정" 버튼 (회의 제목 우측, 아이콘 또는 텍스트 버튼)
|
||||
- 메뉴 버튼 (삭제, 공유 등)
|
||||
|
||||
- **기본 정보 카드**
|
||||
- 회의 일시
|
||||
@@ -1221,14 +1324,12 @@ graph TD
|
||||
- 결정사항 카드 리스트
|
||||
- 각 카드: 결정 내용 + 결정자 + 시간 + 배경 설명
|
||||
|
||||
- **Todo 진행상황 섹션** (📋)
|
||||
- **전체 진행률 표시**: 상단에 원형 진행 바 (완료 Todo 개수 / 전체 Todo 개수)
|
||||
- 진행률 퍼센트 중앙 표시 (예: "60%")
|
||||
- 색상: Primary 색상 (#4DD5A7)
|
||||
- 크기: 80px (Desktop), 60px (Mobile)
|
||||
- 상태별 필터 탭 (전체/시작 전/진행 중/완료)
|
||||
- 담당자별 그룹화
|
||||
- 각 Todo: 제목 + 마감일 + 우선순위 배지 (개별 진행률 바 제거)
|
||||
- **Todo 진행상황 섹션** (📋) - MVP 스코프 축소
|
||||
- **단순 조회만 제공** (UFR-MEET-047)
|
||||
- Todo 리스트:
|
||||
- 각 Todo: 제목 + 담당자 + 마감일만 표시
|
||||
- ❌ 제거: D-day 라벨, 우선순위 배지, 진행률 바, 상태별 필터
|
||||
- ❌ 제거: Todo 관리 화면 연동 (클릭 액션 없음)
|
||||
|
||||
- **참고자료 섹션** (📚)
|
||||
- 참고자료 탭 (관련 회의록/프로젝트 문서/이슈 트래커/위키 페이지)
|
||||
@@ -1237,21 +1338,20 @@ graph TD
|
||||
- 관련도 점수 배지 (92%, 88% 등)
|
||||
- 2-3줄 요약
|
||||
|
||||
- **Todo 섹션** (강조)
|
||||
- **Todo 섹션** (단순 조회) - MVP 스코프 축소
|
||||
- Todo 항목 리스트:
|
||||
- 체크박스 (완료/미완료)
|
||||
- Todo 내용
|
||||
- Todo 내용 (제목)
|
||||
- 담당자 이름
|
||||
- 마감일
|
||||
- 우선순위 배지
|
||||
- ❌ 제거: 체크박스, 우선순위 배지, D-day 라벨
|
||||
|
||||
- **첨부파일 섹션**
|
||||
- 파일 아이콘 + 파일명
|
||||
- 다운로드 버튼
|
||||
|
||||
- **하단 액션 바** (Fixed)
|
||||
- "수정" 버튼 (권한 있는 경우만)
|
||||
- **하단 액션 바** (Fixed) - MVP 스코프 축소
|
||||
- "공유" 버튼
|
||||
- ❌ 제거: "수정" 버튼 (헤더로 이동)
|
||||
|
||||
**Tablet/Desktop (768px+)**
|
||||
- **상단**: 탭 네비게이션
|
||||
@@ -1279,25 +1379,24 @@ graph TD
|
||||
- 관련도 색상 코딩: 90%+ (초록), 70-89% (노랑), 70% 미만 (회색)
|
||||
- "더보기" 클릭 → 전체 참고자료 목록 모달
|
||||
|
||||
3. **대시보드 탭 인터랙션**
|
||||
3. **대시보드 탭 인터랙션** - MVP 스코프 축소
|
||||
- **핵심내용 섹션**:
|
||||
- 키워드 태그 클릭 → 해당 키워드 관련 안건으로 스크롤
|
||||
- 통계 항목 클릭 → 상세 정보 툴팁 표시
|
||||
- **결정사항 섹션**:
|
||||
- 결정사항 카드 클릭 → 회의록 탭의 해당 안건으로 이동
|
||||
- 배경 설명 접기/펼치기
|
||||
- **Todo 진행상황**:
|
||||
- 필터 탭 클릭 → 해당 상태의 Todo만 표시
|
||||
- Todo 카드 클릭 → Todo관리 화면으로 이동
|
||||
- 진행률 바: 실시간 업데이트
|
||||
- **Todo 진행상황** (단순 조회만):
|
||||
- ❌ 제거: 필터 탭, 진행률 바, Todo 관리 화면 연동
|
||||
- Todo는 읽기 전용으로만 표시 (클릭 액션 없음)
|
||||
- **참고자료 섹션**:
|
||||
- 탭 전환 (관련 회의록/프로젝트 문서/이슈 트래커/위키 페이지)
|
||||
- 참고자료 카드 클릭 → 해당 문서로 이동
|
||||
- 관련도 점수: 배지로 표시 (92%, 88% 등)
|
||||
|
||||
4. **Todo 인터랙션**
|
||||
- Todo 체크박스: 완료 처리 (권한 있는 경우)
|
||||
- Todo 클릭: Todo관리 화면으로 이동
|
||||
4. **Todo 인터랙션** - MVP 스코프 축소
|
||||
- ❌ 제거: Todo 체크박스, Todo 관리 화면 연동
|
||||
- Todo는 단순 조회만 가능 (클릭 액션 없음)
|
||||
|
||||
5. **첨부파일 다운로드**
|
||||
- 파일명 클릭: 다운로드 시작
|
||||
@@ -1342,32 +1441,41 @@ graph TD
|
||||
|
||||
#### 개요
|
||||
- **목적**: 지난 회의록 조회 및 수정
|
||||
- **관련 유저스토리**: UFR-MEET-055, UFR-AI-040, **UFR-TODO-040 (Todo 수정)**
|
||||
- **관련 유저스토리**: UFR-MEET-055, UFR-AI-040, UFR-COLLAB-020
|
||||
- **비즈니스 중요도**: 중간
|
||||
- **접근 경로**: 10-회의록상세조회 → 하단 액션 바 "수정" 버튼 클릭
|
||||
- **권한 제어**:
|
||||
- **검증완료 전**: 모든 참석자가 수정 가능
|
||||
- **검증완료 후**: 회의 생성자만 수정 가능 (참석자는 "수정" 버튼 비활성화)
|
||||
|
||||
#### 주요 기능
|
||||
#### 주요 기능 (MVP 스코프 축소 v1.5.2)
|
||||
1. 회의 기본 정보 표시 및 수정
|
||||
- 회의 제목: 수정 가능
|
||||
- 회의 일시/장소: 읽기 전용 (회의 예약 화면에서만 변경 가능)
|
||||
- 참석자 관리: 회의 생성자만 추가/삭제 가능
|
||||
2. **회의록 내용 수정 (안건별)** - 용어 변경: 섹션 → 안건
|
||||
3. **AI 한줄 요약 표시 (안건별, UFR-AI-036)** - 신규
|
||||
- 편집 불가능한 AI 한줄 요약 (30자 이내)
|
||||
- 각 안건 최상단에 표시
|
||||
4. **AI 상세 요약 수정 (안건별)** - 기존 AI 요약 기능
|
||||
5. **참고자료 편집** (추가/제거)
|
||||
6. **Todo 수정 (UFR-TODO-040)** - 회의 생성자만
|
||||
7. **안건별 검증 (UFR-COLLAB-030)** - 신규
|
||||
- 안건별 검증 완료 체크박스
|
||||
- 회의 생성자: 잠금 해제 후 수정 가능
|
||||
- 참석자: 읽기 전용
|
||||
8. 자동 저장 (30초 간격)
|
||||
9. 수정 이력 관리
|
||||
10. 상태 변경 (검증완료 → 작성중으로 자동 변경)
|
||||
3. **AI 요약 표시 및 재생성 (안건별, UFR-AI-036)**
|
||||
- AI 한줄 요약 표시 (30자 이내, 읽기 전용)
|
||||
- 텍스트 편집 영역에서 안건 내용 수정 가능
|
||||
- "AI 재생성" 버튼: 텍스트 편집 영역 내용 기반으로 한줄 요약만 재생성 (2-5초 처리)
|
||||
- 재생성된 한줄 요약은 회의록 상세조회 화면의 대시보드 및 회의록 탭에 즉시 반영
|
||||
4. **참고자료 편집** (추가/제거)
|
||||
5. **Todo 단순 조회** (제목 + 담당자 + 마감일만 표시)
|
||||
6. **안건별 검증 완료 체크박스 (UFR-COLLAB-020)**
|
||||
- 회의 생성자: 검증 완료 체크박스 활성화, 잠금 해제 후 수정 가능
|
||||
- 참석자: 검증완료 안건은 읽기 전용
|
||||
7. 자동 저장 (30초 간격)
|
||||
8. 수정 이력 관리
|
||||
9. 상태 변경 (검증완료 → 작성중으로 자동 변경)
|
||||
|
||||
**변경사항 (v1.5.2)**:
|
||||
- ✅ 명칭 변경: "AI 상세 요약" → "AI 요약"
|
||||
- ✅ 기능 통합: AI 재생성 버튼 클릭 시 텍스트 편집 영역 내용 기반으로 한줄 요약 생성 (UFR-AI-036)
|
||||
- ❌ 제거: AI 상세 요약 및 한줄 요약 분리 표시 (한줄 요약만 표시)
|
||||
- ❌ 제거: 실시간 협업 표시 ("편집 중" 표시 제거)
|
||||
- ❌ 제거: Todo 편집 기능 (체크박스, 담당자/마감일/우선순위 변경, 추가/삭제)
|
||||
- ❌ 제거: 검증률 표시 및 최종 확정 버튼
|
||||
- ✅ 정책: Last Write Wins (마지막 저장 우선) 적용
|
||||
|
||||
#### UI 구성요소
|
||||
|
||||
@@ -1389,45 +1497,35 @@ graph TD
|
||||
- "참석자 추가" 버튼 (이메일 입력 + 초대)
|
||||
- 회의록 상태 배지 (자동 관리)
|
||||
|
||||
- **편집 화면**
|
||||
- **편집 화면** (MVP 스코프 축소)
|
||||
- **안건별 편집 영역** (용어 변경: 섹션 → 안건)
|
||||
- 각 안건:
|
||||
- **안건 헤더**
|
||||
- 안건 제목 (H4, Bold)
|
||||
- 검증 상태 배지 (검증완료/미검증)
|
||||
- 편집 중 표시 (동시 편집 시)
|
||||
- 다른 사용자 아바타 + 이름
|
||||
- 예: "김민준님 편집 중" (아이콘 + 텍스트)
|
||||
- **AI 한줄 요약** (편집 불가, UFR-AI-036) - 신규
|
||||
- 🔒 아이콘 + 30자 이내 한줄 요약
|
||||
- 읽기 전용 (회색 배경, 민트 그린 좌측 액센트 라인)
|
||||
- ❌ 제거: "편집 중" 표시 (실시간 협업 기능 제거)
|
||||
- **AI 요약** (읽기 전용, UFR-AI-036)
|
||||
- 💡 "AI 요약" 레이블
|
||||
- AI 한줄 요약 표시 (30자 이내)
|
||||
- 읽기 전용 영역 (회색 배경, 민트 그린 좌측 액센트 라인)
|
||||
- 호버 시: "이 내용은 편집할 수 없습니다" 툴팁
|
||||
- **AI 상세 요약 편집 영역**
|
||||
- 💡 "AI 상세 요약" 레이블 (명칭 변경)
|
||||
- 요약 텍스트 편집 필드 (textarea)
|
||||
- "AI 재생성" 버튼 (요약 다시 생성)
|
||||
- **텍스트 편집 영역**
|
||||
- 안건 내용 편집 필드 (textarea)
|
||||
- 논의 주제, 발언자별 의견, 결정 사항, 보류 사항 등 자유 작성
|
||||
- "AI 재생성" 버튼: 텍스트 편집 영역 내용 기반으로 AI 요약의 한줄 요약 재생성
|
||||
- 마지막 수정 시간 표시
|
||||
- 편집 가능한 텍스트 영역
|
||||
- 논의 주제
|
||||
- 발언자별 의견
|
||||
- 결정 사항
|
||||
- 보류 사항
|
||||
- **참고자료 편집 영역**
|
||||
- 기존 참고자료 목록 (제거 버튼 포함)
|
||||
- "참고자료 추가" 버튼
|
||||
- 회의록 검색 및 선택 UI
|
||||
- **Todo 섹션 편집 영역** (회의 생성자만)
|
||||
- Todo 목록 표시
|
||||
- **Todo 섹션 단순 조회** (편집 불가)
|
||||
- Todo 목록 표시 (읽기 전용)
|
||||
- 각 Todo 항목:
|
||||
- 체크박스 (완료 상태)
|
||||
- Todo 제목
|
||||
- 담당자 (변경 가능)
|
||||
- 마감일 (변경 가능)
|
||||
- 우선순위 (변경 가능)
|
||||
- "편집" 버튼 (인라인 편집 활성화)
|
||||
- "삭제" 버튼
|
||||
- "Todo 추가" 버튼
|
||||
- **안건별 검증 영역** (UFR-COLLAB-030) - 신규
|
||||
- 담당자
|
||||
- 마감일
|
||||
- ❌ 제거: 체크박스, 우선순위 배지, D-day 라벨, 편집/삭제 버튼
|
||||
- **안건별 검증 영역** (UFR-COLLAB-020)
|
||||
- **회의 생성자 화면**:
|
||||
- 검증 완료 체크박스 (활성화)
|
||||
- "잠금 해제" 버튼 (검증완료 안건만 표시)
|
||||
@@ -1456,38 +1554,36 @@ graph TD
|
||||
- 자동 저장: 30초 간격, 인디케이터 표시
|
||||
- 수동 저장: "저장" 버튼 클릭
|
||||
|
||||
3. **AI 한줄 요약 확인 (UFR-AI-036)** - 신규
|
||||
3. **AI 한줄 요약 확인 (UFR-AI-036)** - MVP 스코프 축소
|
||||
- **읽기 전용 표시**:
|
||||
- 🔒 아이콘으로 편집 불가 명시
|
||||
- 회색 배경 + 민트 그린 좌측 액센트 라인
|
||||
- **호버 인터랙션**:
|
||||
- 툴팁 표시: "이 내용은 편집할 수 없습니다"
|
||||
- 툴팁 표시: "이 내용은 편집할 수 없습니다. 회의 종료 시 1회만 생성됩니다."
|
||||
- **위치**: 각 안건 최상단 (안건 제목 바로 아래)
|
||||
- ❌ 제거: "AI 재생성" 버튼 (한줄 요약은 회의 종료 시 1회만 생성)
|
||||
|
||||
4. **AI 상세 요약 편집**
|
||||
4. **AI 상세 요약 편집** - MVP 스코프 축소
|
||||
- 요약 텍스트 필드 클릭: 직접 수정 가능
|
||||
- "AI 재생성" 버튼 클릭:
|
||||
- 현재 안건 내용 기반으로 상세 요약 재생성
|
||||
- 현재 안건 내용 기반으로 **상세 요약만** 재생성 (한줄 요약 제외)
|
||||
- 로딩 인디케이터 표시
|
||||
- 생성 완료 시 자동 업데이트
|
||||
- 자동 저장 (30초 간격)
|
||||
|
||||
5. **안건별 검증 (UFR-COLLAB-030)** - 신규
|
||||
5. **안건별 검증 완료 체크박스 (UFR-COLLAB-020)** - MVP 스코프 축소
|
||||
- **회의 생성자 권한**:
|
||||
- 검증 완료 체크박스 클릭:
|
||||
- 체크: 안건 검증 완료 처리 (배지 "검증완료"로 변경)
|
||||
- 언체크: 미검증 상태로 변경
|
||||
- "잠금 해제" 버튼 클릭 (검증완료 안건만 표시):
|
||||
- 확인 다이얼로그: "이 안건의 잠금을 해제하시겠습니까?"
|
||||
- 확인 시: 안건 편집 가능 상태로 변경
|
||||
- 확인 시: 안건 검증 완료 체크 해제 → 편집 가능 상태로 변경
|
||||
- **참석자 화면**:
|
||||
- 검증완료 안건: 🔒 "읽기 전용" 배지 표시
|
||||
- 안내 텍스트: "(잠금됨 · 회의 생성자만 수정 가능)"
|
||||
- 모든 입력 필드 비활성화 (disabled)
|
||||
- **검증률 계산 및 표시**:
|
||||
- 검증률 = 검증 완료된 안건 수 / 전체 안건 수
|
||||
- 헤더에 검증률 표시 (예: "검증률: 70% (7/10)")
|
||||
- 모든 안건 검증 완료 시 "최종 확정" 버튼 활성화
|
||||
- ❌ 제거: 검증률 계산 및 표시, "최종 확정" 버튼
|
||||
|
||||
6. **참고자료 편집**
|
||||
- "참고자료 추가" 버튼 클릭:
|
||||
@@ -1497,98 +1593,72 @@ graph TD
|
||||
- 제거 버튼 (X): 참고자료 목록에서 제거
|
||||
- 순서 변경: 드래그하여 순서 조정 (선택)
|
||||
|
||||
7. **Todo 섹션 편집 (UFR-TODO-040)** (회의 생성자만)
|
||||
- **권한 제어**:
|
||||
- 회의 생성자만 Todo 섹션 편집 가능
|
||||
- 일반 참석자는 조회만 가능 (편집 버튼 숨김)
|
||||
- **편집 버튼 클릭**:
|
||||
- 인라인 편집 모드 활성화
|
||||
- **수정 가능 항목** (회의 생성자 권한):
|
||||
- ✏️ Todo 제목
|
||||
- 👤 담당자 (드롭다운 선택, 참석자 목록)
|
||||
- 📅 마감일 (날짜 선택기)
|
||||
- 🎯 우선순위 (high/medium/low)
|
||||
- "저장" 버튼: 수정 완료
|
||||
- "취소" 버튼: 편집 모드 취소
|
||||
- **수정 완료 시**:
|
||||
- "Todo가 수정되었습니다" 토스트 메시지
|
||||
- 회의록 자동 저장
|
||||
- 담당자 변경 시: 이전/새 담당자에게 알림 발송
|
||||
- 마감일 변경 시: 캘린더 자동 업데이트
|
||||
- **Todo 추가**:
|
||||
- "Todo 추가" 버튼 클릭
|
||||
- Todo 정보 입력 모달 (제목, 담당자, 마감일, 우선순위)
|
||||
- 저장 시 Todo 목록에 추가
|
||||
- **Todo 삭제**:
|
||||
- "삭제" 버튼 클릭
|
||||
- 확인 다이얼로그 ("삭제하시겠습니까?")
|
||||
- 삭제 시 Todo 목록에서 제거
|
||||
- 담당자에게 삭제 알림 발송
|
||||
7. **Todo 섹션 단순 조회** - MVP 스코프 축소
|
||||
- ❌ 제거: Todo 편집/추가/삭제 기능 전체 제거
|
||||
- Todo는 읽기 전용으로만 표시 (제목 + 담당자 + 마감일)
|
||||
- 모든 사용자 (생성자 포함)에게 조회만 가능
|
||||
|
||||
8. **상태 변경**
|
||||
8. **상태 변경** - MVP 스코프 축소
|
||||
- 확정완료 회의록 수정 시: 자동으로 "작성중" 상태로 변경
|
||||
- 모든 안건 검증 완료 시: "확정완료"로 변경 제안
|
||||
- ❌ 제거: "확정완료"로 변경 제안 (검증률 기능 제거로 인해)
|
||||
|
||||
9. **저장 로직** - MVP 스코프 축소
|
||||
- **"저장" 버튼 클릭 시**:
|
||||
- 검증완료된 안건: 저장 스킵
|
||||
- 미검증 안건: 저장 진행
|
||||
- **저장 결과 알림**:
|
||||
- "N개 안건이 저장되었습니다"
|
||||
- "M개 안건은 검증완료 상태로 저장되지 않았습니다"
|
||||
- 저장 불가 안건 목록 표시
|
||||
- **자동 저장** (30초 간격):
|
||||
- 미검증 안건만 자동 저장
|
||||
- 검증완료 안건은 자동 저장 스킵
|
||||
|
||||
9. **안건 기반 충돌 해결 (UFR-COLLAB-020)**
|
||||
10. **안건 기반 충돌 해결 (UFR-COLLAB-020)** - MVP 스코프 축소
|
||||
- **안건 기반 충돌 방지 메커니즘**:
|
||||
- **다른 안건 동시 편집**: 충돌 없음
|
||||
- 참석자 A가 안건 1 편집 중
|
||||
- 참석자 A가 안건 1 편집
|
||||
- 참석자 B가 안건 2 편집 가능
|
||||
- 양쪽 모두 정상 저장 및 동기화
|
||||
- 양쪽 모두 정상 저장
|
||||
|
||||
- **동일 안건 내 다른 필드 편집**: 자동 병합
|
||||
- 참석자 A가 안건 1의 "상세 요약" 편집
|
||||
- 참석자 B가 안건 1의 "관련회의록" 편집
|
||||
- 양쪽 변경 사항 자동 병합
|
||||
- **동일 안건 검증 완료 체크로 충돌 방지**:
|
||||
- 검증완료된 안건: 편집 불가 (회의 생성자만 잠금 해제 가능)
|
||||
- 미검증 안건: Last Write Wins (마지막 저장 우선)
|
||||
|
||||
- **동일 필드 동시 수정**: Last Write Wins
|
||||
- 마지막에 저장된 변경 사항이 적용
|
||||
- 덮어쓰기 경고: "다른 사용자가 이미 수정했습니다. 최신 내용을 확인하세요"
|
||||
- 선택 옵션: 최신 내용 확인 / 내 변경 사항 유지
|
||||
- 별도 경고 없이 덮어쓰기
|
||||
|
||||
- **편집 중 표시**:
|
||||
- 다른 사용자가 편집 중인 안건 표시
|
||||
- 편집자 아바타 + 이름 실시간 표시
|
||||
- 예: "김민준님이 이 안건을 편집 중입니다" + 아바타
|
||||
- 편집 시작 시 해당 안건에 브로드캐스트
|
||||
- 편집 종료 시 표시 제거
|
||||
- ❌ 제거: 실시간 "편집 중" 표시
|
||||
- ❌ 제거: 충돌 경고 모달 및 선택 옵션
|
||||
|
||||
- **충돌 경고 모달**:
|
||||
- 제목: "동시 수정 감지"
|
||||
- 메시지: "다른 사용자가 이미 이 내용을 수정했습니다"
|
||||
- 옵션 버튼:
|
||||
- "최신 내용 보기" (Primary): 다른 사용자 변경사항 로드
|
||||
- "내 변경사항 유지" (Secondary): 현재 내용 유지 (덮어쓰기)
|
||||
|
||||
#### 데이터 요구사항
|
||||
#### 데이터 요구사항 (MVP 스코프 축소)
|
||||
- **입력**:
|
||||
- 회의록 ID (조회)
|
||||
- 수정 내용 (안건 ID, 내용) - 용어 변경: 섹션 → 안건
|
||||
- **AI 한줄 요약** (읽기 전용, 입력 불가) - 신규
|
||||
- **AI 한줄 요약** (읽기 전용, 입력 불가)
|
||||
- **AI 상세 요약 수정** (안건 ID, 요약 내용)
|
||||
- **참고자료 변경** (추가/제거할 회의록 ID)
|
||||
- **안건별 검증 상태** (안건 ID, 검증 여부) - 신규
|
||||
- **안건별 검증 상태** (안건 ID, 검증 여부)
|
||||
- **출력**:
|
||||
- 회의록 목록 (필터/정렬/검색 결과)
|
||||
- 수정 결과 (성공/실패)
|
||||
- **AI 한줄 요약** (회의 종료 시 생성, 편집 불가) - 신규
|
||||
- **AI 상세 요약 재생성 결과**
|
||||
- **AI 한줄 요약** (회의 종료 시 생성, 편집 불가)
|
||||
- **AI 상세 요약 재생성 결과** (한줄 요약 제외)
|
||||
- 수정 이력 (누가, 언제, 무엇을)
|
||||
- **검증률** (검증 완료된 안건 수 / 전체 안건 수) - 신규
|
||||
- **연동**: Meeting 서비스, AI 서비스 (UFR-AI-010, UFR-AI-036, UFR-AI-040), Collaboration 서비스 (UFR-COLLAB-030)
|
||||
- ❌ 제거: 검증률 출력
|
||||
- **연동**: Meeting 서비스, AI 서비스 (UFR-AI-010, UFR-AI-036, UFR-AI-040), PARTICIPANT 서비스 (UFR-COLLAB-020)
|
||||
|
||||
#### 에러 처리
|
||||
#### 에러 처리 (MVP 스코프 축소)
|
||||
- **권한 없음**: "본인이 작성한 회의록만 수정할 수 있습니다"
|
||||
- **자동 저장 실패**: "네트워크 연결을 확인해주세요. 로컬에 임시 저장됩니다"
|
||||
- **AI 요약 재생성 실패**: "요약 생성에 실패했습니다. 수동으로 작성해주세요"
|
||||
- **참고자료 검색 실패**: "회의록을 검색할 수 없습니다"
|
||||
- **충돌 발생**:
|
||||
- 안건 기반 충돌 방지로 최소화
|
||||
- 동일 필드 동시 수정 시: "다른 사용자가 이미 수정했습니다" 경고 모달
|
||||
- 선택 옵션: 최신 내용 확인 / 내 변경사항 유지
|
||||
- 병합 실패 시: "병합 중 오류가 발생했습니다" 에러 메시지
|
||||
- **검증완료 안건 저장 시도**:
|
||||
- 저장 결과 알림: "N개 안건이 저장되었습니다. M개 안건은 검증완료 상태로 저장되지 않았습니다"
|
||||
- 저장 불가 안건 목록 표시
|
||||
- **삭제 실패**: "회의록 삭제에 실패했습니다"
|
||||
- ❌ 제거: 충돌 경고 모달 (Last Write Wins 적용으로 인해)
|
||||
|
||||
---
|
||||
|
||||
@@ -1795,6 +1865,8 @@ graph TD
|
||||
- 필터링 결과 없음: "조건에 맞는 회의록이 없습니다"
|
||||
- 전체 회의록 없음: "회의록이 없습니다. 첫 회의를 시작해보세요!" + 회의 시작 버튼
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 공통 UI 컴포넌트
|
||||
@@ -1853,6 +1925,8 @@ graph TD
|
||||
- **Desktop (768px+)**:
|
||||
- 프로필 아이콘 숨김 (사이드바 하단 영역 사용)
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 공통 에러 메시지 표준
|
||||
@@ -1892,6 +1966,8 @@ graph TD
|
||||
- **로깅**: 오류 상세 정보를 서버로 전송 (Sentry)
|
||||
- **적용 화면**: 전체
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 화면 간 전환 및 네비게이션
|
||||
@@ -1923,6 +1999,8 @@ graph TD
|
||||
- 특정 Todo 직접 접근: `/todo/{todoId}`
|
||||
- 회의록 공유 링크: `/share/{shareToken}`
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 반응형 설계 전략
|
||||
@@ -1974,6 +2052,8 @@ graph TD
|
||||
- Lazy Loading: 뷰포트 진입 시 로딩
|
||||
- 최적화: WebP 포맷, 적절한 압축
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 접근성 보장 방안
|
||||
@@ -2011,6 +2091,8 @@ graph TD
|
||||
- 자동 테스트: Lighthouse, axe DevTools
|
||||
- 수동 테스트: 키보드 네비게이션, 스크린 리더 (NVDA, JAWS, VoiceOver)
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 성능 최적화 방안
|
||||
@@ -2062,13 +2144,14 @@ graph TD
|
||||
- **STT 지연 시간**: < 1s
|
||||
- **실시간 동기화 지연**: < 500ms
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
## 변경 이력
|
||||
|
||||
| 버전 | 날짜 | 작성자 | 변경 내용 |
|
||||
|------|------|--------|----------|
|
||||
| 1.4.20 | 2025-10-25 | 이미준, 강지수 | 유저스토리 v2.3.0 반영<br>- 회의 종료 화면 정책 명확화 (확인 전용, 바로 최종 확정 옵션 상세화)<br>- UFR-MEET-050: 최종 확정 2가지 시나리오 설명 추가<br>- UFR-COLLAB-020: 안건 기반 충돌 해결 메커니즘 상세 추가<br>- 실시간 협업 충돌 방지 정책 강화 |
|
||||
| 1.0 | 2025-10-21 | 이미준 | 최초 작성 - 11개 화면 설계 완료 |
|
||||
| 1.1 | 2025-10-21 | 이미준 | AI 요약 및 참고자료 기능 추가<br>- 05-회의진행: AI 회의 내용 요약 자동 생성 및 참고자료 자동 연결 추가<br>- 10-회의록상세조회: 섹션별 AI 요약 표시 및 참고자료 영역 추가<br>- 11-회의록수정: AI 요약 수정 및 참고자료 편집 기능 추가<br>- 관련 유저스토리: UFR-AI-040 (관련 회의록 자동 연결) |
|
||||
| 1.1.1 | 2025-10-21 | 이미준 | 회의록 상세 화면 구조 개선 (프로토타입 기반)<br>- 10-회의록상세조회: 탭 기반 네비게이션 추가 (회의록/대시보드)<br>- 대시보드 탭 추가: 핵심내용, 결정사항, Todo 진행상황, 참고자료 섹션<br>- 참고자료 관련도 점수 표시 (백분율 + 색상 코딩)<br>- 참고자료 카테고리 탭 (관련 회의록/프로젝트 문서/이슈 트래커/위키 페이지)<br>- 참조: design-gappa/uiux/prototype 파일 (11-회의록대시보드.html, 05-회의진행.html) |
|
||||
@@ -2102,7 +2185,12 @@ graph TD
|
||||
|| 1.4.17 | 2025-10-24 | 강지수 | 07-회의종료 화면 STT 한계 반영 (유저스토리 v2.1.2)<br>- **STT 화자 식별 불가 반영**: STT는 화자를 식별할 수 없으므로 화자 관련 기능 제거<br> - 발언 통계 섹션 삭제<br> - 안건별 "발언자별 의견" 섹션 삭제<br>- **통계 영역 디자인 개선**: 정보성 디자인으로 명확화<br> - 배경색: var(--white) → var(--gray-50)<br> - 숫자 색상: var(--primary) → var(--gray-900)<br> - 라벨 색상: var(--gray-500) → var(--gray-600)<br> - 정보 표시 전용으로 시각적 구분 명확화<br>- **안건 섹션 구분 개선**:<br> - 안건 간 하단 보더 추가 (1px solid var(--gray-200))<br> - 섹션 제목에 primary 색상 세로 바 추가 (::before pseudo-element)<br> - 콘텐츠 영역 좌측 패딩 추가로 계층 구조 명확화<br>- **연관 문서 업데이트**:<br> - 유저스토리 UFR-MEET-040: "발언 횟수 (화자별)" 항목 제거<br> - UI/UX 설계서 07-회의종료: 발언 통계 및 발언자별 의견 항목 제거 |
|
||||
| 1.4.18 | 2025-10-24 | 강지수 | 05-회의진행 실시간 주요 메모 추천 기능 명확화 (유저스토리 v2.1.1)<br>- **AI 제안 탭 기능 상세화**: 실시간 주요 메모 추천 기능 명시 추가<br> - UFR-MEET-030: 실시간 AI 주요 메모 추천<br> - 음성→텍스트 변환 후 AI가 실시간 분석<br> - **중요한 내용으로 판단된 경우에만** 주요 메모 항목 추천<br> - 추천 빈도는 중요 내용 발생에 따라 가변적 (3-5초 고정 간격 아님)<br> - 각 추천 항목에 "주요 메모에 추가" 버튼 제공<br> - 실시간 업데이트: 새로운 추천은 상단에 표시<br>- **프로토타입 확인**: 05-회의진행.html의 AI 제안 탭이 실시간 주요 메모 추천 기능을 포함하고 있음을 확인<br>- **참조**: design/uiux/요구사항설계검토-report-V1.2.md (실시간 주요 메모 추천 명시 부족 개선) |
|
||||
| 1.4.19 | 2025-10-24 | 강지수 | 05-회의진행 화면 설계서 프로토타입 기준 전면 수정<br>- **레이아웃 구조 변경**: "2열 구조" 표현 제거, "메인 콘텐츠 영역: 정보 패널 (탭 구조)"로 단순화<br> - 텍스트 편집 영역 관련 내용 모두 제거 (왼쪽 영역, 에디터 툴바, contentEditable 등)<br> - 현재 프로토타입은 헤더 + 탭 콘텐츠 구조만 보유<br>- **반응형 디자인 명확화**: Mobile/Desktop 모두 동일한 구조에 너비만 반응형<br> - "2열 구조를 1열로 전환", "바텀시트" 표현 제거<br> - Mobile: 전체 너비 사용, Desktop: 최대 너비 제한 없이 반응형<br>- **AI 제안 탭 기능 명확화**: 논의항목/결정사항 구분 제거<br> - "논의항목/결정사항 등의 구분 없이 중요 내용을 주요 메모로 제안" 명시<br> - AI는 단순히 중요한 내용을 주요 메모 항목으로 제안하는 역할만 수행<br>- **용어 사전 검색 기능 추가**: 검색 입력창 + 검색 버튼<br> - Enter 키 지원, 용어명과 정의 모두 검색<br> - 검색 동작 상세 설명: 일치하는 용어만 표시, 하이라이트 효과, 결과 없으면 전체 목록 표시<br>- **인터랙션 섹션 정리**: 텍스트 편집, 툴바 사용, 충돌 감지 등 편집 관련 내용 모두 제거<br> - 탭 전환, 회의 종료, 실시간 업데이트만 유지<br> - 실시간 업데이트 항목을 현재 화면에 맞게 수정 (AI 제안, 용어 사전, 관련 회의록)<br>- **데이터 요구사항 업데이트**: 사용자 편집 내용 제거, 참석자 초대 이메일 추가<br> - AI 제안을 "주요 메모 항목 제안"으로 명확히 표현<br>- **에러 처리 업데이트**: 편집 충돌 에러 제거, 용어 사전 로드 실패/참석자 초대 실패 추가<br>- **주요 기능 목록 정리**: 실시간 협업/수동 편집 제거, AI 주요 메모 제안/참석자 관리 추가<br>- **권한 항목 수정**: "회의록 편집: 모든 참석자" → "참석자 초대: 모든 참석자"<br>- **프로토타입 기준 반영**: 05-회의진행.html 실제 구현 상태 100% 반영 |
|
||||
| 1.4.20 | 2025-10-25 | 이미준, 강지수 | 유저스토리 v2.3.0 반영<br>- 회의 종료 화면 정책 명확화 (확인 전용, 바로 최종 확정 옵션 상세화)<br>- UFR-MEET-050: 최종 확정 2가지 시나리오 설명 추가<br>- UFR-COLLAB-020: 안건 기반 충돌 해결 메커니즘 상세 추가<br>- 실시간 협업 충돌 방지 정책 강화 |
|
||||
| 1.5.1 | 2025-10-27 | 강지수 | MVP 스코프 축소 v2.4.0 반영 (4개 화면 수정)<br>- **02-대시보드**: Todo 위젯 및 통계 제거 (UFR-USER-020 반영)<br> - Todo 위젯 전체 제거 (나의 Todo 섹션 삭제)<br> - 통계 카드: "나의 Todo" 제거, "작성중 회의록" 유지 (2개 항목)<br> - 네비게이션: 하단 네비게이션 및 사이드바에서 Todo 관리 메뉴 제거<br> - Desktop 통계 그리드: 2개 항목만 표시<br>- **05-회의진행**: "AI 제안" 탭 → "AI 기반 메모" 탭 기능 변경<br> - 메모 입력창 + 저장 버튼 추가<br> - AI가 감지한 주요 내용 리스트 표시 (시간 + 내용)<br> - 각 참석자별 개별 저장, 다른 참석자 메모 볼 수 없음<br> - 메모는 회의 종료 전까지만 표시/편집 가능<br> - 에러 처리: AI 주요 내용 감지 실패, 메모 저장 실패 추가<br>- **10-회의록상세조회**: Todo 단순 조회 기능으로 변경<br> - Todo는 제목 + 담당자 + 마감일만 표시<br> - D-day 라벨, 우선순위 배지, 진행률 바, 상태별 필터 제거<br> - Todo 관리 화면 연동 링크 제거 (화면 자체가 제거됨)<br> - "수정" 버튼을 헤더로 이동<br>- **11-회의록수정**: 실시간 협업 기능 제거, 안건 기반 충돌 방지 강화<br> - "편집 중" 표시 제거 (실시간 협업 기능 제거)<br> - Todo 편집/추가/삭제 기능 전체 제거 (단순 조회만 가능)<br> - AI 한줄 요약 재생성 불가 (회의 종료 시 1회만 생성)<br> - 검증률 표시 및 최종 확정 버튼 제거<br> - 저장 로직 추가: 검증완료 안건 저장 스킵, 저장 결과 알림<br> - 안건별 검증 완료 체크박스로 충돌 방지 (Last Write Wins 적용)<br> - 에러 처리: 충돌 경고 모달 제거 (LWW로 인해) |
|
||||
| 1.5.2 | 2025-10-27 | 강지수 | AI 요약 기능 통합 및 단순화 (유저스토리 v2.4.0 반영)<br>- **11-회의록수정**: AI 요약 기능 통합<br> - 명칭 변경: "AI 상세 요약" → "AI 요약"<br> - AI 요약 영역: AI 한줄 요약만 표시 (30자 이내, 읽기 전용)<br> - 텍스트 편집 영역: 안건 내용 자유 작성 (논의 주제, 발언자별 의견, 결정 사항 등)<br> - "AI 재생성" 버튼: 텍스트 편집 영역 내용 기반으로 AI 요약의 한줄 요약 재생성 (2-5초 처리)<br> - 재생성된 한줄 요약은 회의록 상세조회 화면의 대시보드 및 회의록 탭에 즉시 반영<br> - AI 상세 요약 및 한줄 요약 분리 표시 제거<br>- **프로토타입 UI 개선**:<br> - AI 재생성 버튼 스타일 통일: btn-secondary → btn-primary (다른 화면과 일관성)<br> - 안건별 검증완료 UI 단순화: 참석자는 체크박스만, 회의 생성자는 검증완료 시 잠금해제 버튼 표시<br> - .creator-only CSS 클래스 추가: data-is-creator 속성 기반 표시 제어<br>- **관련 유저스토리**: UFR-AI-036 (AI 한줄요약 확인 및 재생성), UFR-MEET-055 (안건별 검증), UFR-COLLAB-030 (충돌 방지) |
|
||||
| 1.5.3 | 2025-10-27 | 강지수 | Todo 추가/편집 권한 정책 명확화 (유저스토리 v2.4.1 반영)<br>- **10-회의록상세조회**: Todo 추가/편집 권한 정책 추가 (대시보드 탭)<br> - "추가" 버튼: 모든 회의 참석자에게 노출 (Todo 리스트 우측 상단)<br> - "편집(✏️)" 버튼: 회의 생성자에게만 노출 (각 Todo 항목 우측)<br> - Todo 추가 모달: 제목, 담당자, 마감일 입력 (모든 참석자)<br> - Todo 편집 모달: 제목, 담당자, 마감일 수정 (회의 생성자만)<br> - 담당자 필드: 추가 시 또는 생성자의 편집 시만 표시<br>- **프로토타입 UI 개선**: 10-회의록상세조회.html<br> - Todo 추가/편집 모달 바텀시트 스타일 통일 (모바일: 하단 슬라이드 업, 데스크톱: 중앙 모달)<br> - .creator-only 클래스 적용하여 편집 버튼 권한별 표시/숨김 처리<br> - JavaScript initPage() 함수에서 회의 생성자 여부 확인 후 creator-only 요소 제어<br> - Todo 추가 성공: "담당자에게 알림이 전송되었습니다" → "캘린더가 업데이트되었습니다" 순차 토스트<br> - Todo 편집 성공: 담당자 변경 시 알림, 마감일 변경 시 캘린더 업데이트 토스트<br>- **관련 유저스토리**: UFR-MEET-047 (회의록상세조회), Todo 권한 정책 신규 추가 |
|
||||
|
||||
[↑ 목차로 돌아가기](#목차)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -0,0 +1,203 @@
|
||||
# 유저스토리 목록 (v2.4.1)
|
||||
|
||||
최종 수정일: 2025-10-27
|
||||
|
||||
## 📋 전체 유저스토리 목록
|
||||
|
||||
| ID | 서비스 | 역할 | 제목 | As a | I want to | So that | 상태 |
|
||||
|---|---|---|---|---|---|---|---|
|
||||
| UFR-USER-010 | User | 사용자 | 로그인 | 사용자로서 | 사번과 비밀번호로 로그인 | 시스템에 접근하기 위해 | ✅ |
|
||||
| UFR-USER-020 | User | 사용자 | 대시보드 | 사용자로서 | 대시보드를 조회 | 나의 회의 현황을 파악하기 위해 | ✅ |
|
||||
| UFR-MEET-010 | Meeting | 회의 생성자 | 회의예약 | 회의 생성자로서 | 회의를 예약하고 참석자를 초대 | 회의를 효율적으로 준비하기 위해 | ✅ |
|
||||
| UFR-MEET-015 | Meeting | 회의 참석자 | 회의진행 중 참석자 초대 | 회의 참석자로서 | 실시간으로 참석자를 초대 | 회의 중 추가 참석자가 필요할 때 | ✅ |
|
||||
| UFR-MEET-020 | Meeting | 회의 생성자 | 템플릿선택 | 회의 생성자로서 | 회의 유형에 맞는 템플릿을 선택 | 회의록을 효율적으로 작성하기 위해 | ✅ |
|
||||
| UFR-MEET-030 | Meeting | 회의 생성자 | 회의시작 | 회의 생성자로서 | 회의를 시작하고 음성 녹음을 준비 | 회의를 시작하고 회의록을 작성하기 위해 | ✅ v2.4.1 개선 |
|
||||
| UFR-MEET-040 | Meeting | 회의 생성자 | 회의종료 | 회의 생성자로서 | 회의를 종료하고 요약 내용을 확인한 후 다음 단계를 선택 | 회의를 종료하고 회의록을 정리하기 위해 | ✅ v2.4.1 수정 |
|
||||
| UFR-MEET-050 | Meeting | 회의 생성자 | 최종확정 | 회의 생성자로서 | 모든 안건을 검증하고 최종 회의록을 확정 | 회의록을 완성하기 위해 | ✅ |
|
||||
| UFR-MEET-046 | Meeting | 회의 참석자 | 회의록목록조회 | 회의 참석자로서 | 회의록 목록을 조회하고 필터링 | 참여한 회의록들을 효율적으로 관리하기 위해 | ✅ |
|
||||
| UFR-MEET-047 | Meeting | 회의 참석자 | 회의록상세조회 | 회의 참석자로서 | 지난 회의록의 상세 정보와 전체 내용을 한눈에 확인 | 회의록을 효율적으로 검토하기 위해 | ✅ |
|
||||
| UFR-MEET-055 | Meeting | 회의 참석자 | 회의록수정 | 회의 참석자로서 | 검증이 완료되지 않은 안건을 수정하고 검증완료 체크 | 회의록의 정확성을 보장하기 위해 | ✅ |
|
||||
| UFR-AI-010 | AI | 회의 참석자 | 회의록자동작성 | 회의 참석자로서 | AI가 발언 내용을 실시간으로 정리하고 회의 종료 시 전체 안건을 요약 | 회의록 작성 부담을 줄이기 위해 | ✅ |
|
||||
| UFR-AI-020 | AI | 회의 참석자 | Todo자동추출 | 회의 참석자로서 | AI가 안건별 내용에서 Todo 항목을 자동으로 추출하고 기본값을 설정 | 회의 후 실행 사항을 명확히 하기 위해 | ✅ |
|
||||
| UFR-AI-030 | AI | 회의 참석자 | 실시간AI제안 | 회의 참석자로서 | AI가 실시간으로 주요 내용을 분석하여 제안 | 회의 중 놓치는 내용을 최소화하기 위해 | ✅ |
|
||||
| UFR-AI-036 | AI | 회의 참석자 | AI한줄요약 | 회의 참석자로서 | AI가 생성한 한줄 요약을 확인하고 필요 시 재생성 | 각 안건의 핵심을 빠르게 파악하기 위해 | ✅ |
|
||||
| UFR-AI-040 | AI | 회의 참석자 | 관련회의록연결 | 회의 참석자로서 | AI가 같은 폴더 내 관련 있는 과거 회의록을 자동으로 찾아 연결하고 유사 내용을 요약 | 이전 회의 내용을 쉽게 참조하기 위해 | ✅ v2.4.1 개선 |
|
||||
| UFR-STT-010 | STT | 회의 참석자 | 음성녹음인식 | 회의 참석자로서 | 음성이 실시간으로 녹음되고 인식 | 발언 내용이 자동으로 기록되기 위해 | ✅ |
|
||||
| UFR-STT-020 | STT | 시스템 | 텍스트변환 | 회의록 시스템으로서 | 음성을 텍스트로 변환 | 인식된 발언을 회의록에 기록하기 위해 | ✅ |
|
||||
| UFR-RAG-010 | AI (RAG) | 회의 참석자 | 전문용어감지 | 회의 참석자로서 | 전문용어가 자동으로 감지되고 맥락에 맞는 설명을 제공 | 업무 지식이 없어도 회의록을 정확히 작성하기 위해 | ✅ |
|
||||
| UFR-RAG-020 | AI (RAG) | 회의 참석자 | 맥락기반용어설명 | 회의 참석자로서 | 관련 회의록과 업무 이력을 바탕으로 실용적인 설명을 제공 | 전문용어를 맥락에 맞게 이해하기 위해 | ✅ |
|
||||
| UFR-COLLAB-010 | Meeting | 회의 참석자 | 회의록수정동기화 | 회의 참석자로서 | 회의록을 수정하고 실시간으로 다른 참석자와 동기화 | 회의록을 함께 검증하기 위해 | ✅ |
|
||||
| UFR-COLLAB-020 | Meeting | 회의 참석자 | 충돌해결 | 회의 참석자로서 | 안건별로 충돌 없이 편집 | 동시 수정 상황에서도 내용을 잃지 않기 위해 | ✅ |
|
||||
| UFR-COLLAB-030 | Meeting | 회의 참석자 | 검증완료 | 회의 참석자로서 | 각 안건을 검증하고 완료 표시 | 회의록의 정확성을 보장하기 위해 | ✅ |
|
||||
| UFR-NOTI-010 | Notification | 시스템 | 알림발송 | Notification 시스템으로서 | 주기적으로 알림 대상을 확인하여 이메일을 발송 | 사용자에게 중요한 이벤트를 알리기 위해 | ✅ |
|
||||
| UFR-PART-010 | Meeting | 회의 참석자 | 회의입장 | 회의 참석자로서 | 대시보드에서 "참여하기" 버튼으로 회의에 입장 | 예정된 회의에 참여하기 위해 | ✅ v2.4.1 신규 |
|
||||
| UFR-PART-020 | Meeting | 회의 참석자 | AI기반메모작성 | 회의 참석자로서 | AI가 추천한 주요 내용을 메모 입력창에 추가하고 편집 | 중요한 내용을 메모로 기록하기 위해 | ✅ v2.4.1 신규 |
|
||||
| UFR-PART-030 | Meeting | 회의 참석자 | 회의중도퇴장 | 회의 참석자로서 | "나가기" 버튼으로 회의에서 퇴장 | 회의를 중간에 나가야 할 때 | ✅ v2.4.1 신규 |
|
||||
| UFR-HOST-010 | Meeting | 회의 생성자 | 회의종료권한 | 회의 생성자로서 | "회의 종료" 버튼으로만 회의를 종료 | 회의를 마무리하기 위해 | ✅ v2.4.1 신규 |
|
||||
| UFR-HOST-020 | Meeting | 회의 생성자 | 녹음제어권한 | 회의 생성자로서 | 녹음 일시정지/재개/종료 권한을 가짐 | 녹음을 관리하기 위해 | ✅ v2.4.1 신규 |
|
||||
| UFR-TERM-010 | AI | 회의 참석자 | 용어자동감지 | 회의 참석자로서 | AI가 자동으로 감지한 용어를 "용어" 탭에서 확인 | 전문용어를 이해하기 위해 | ✅ v2.4.1 신규 |
|
||||
| UFR-TERM-020 | AI | 회의 참석자 | 회사용어사전 | 회의 참석자로서 | 회사 용어 사전에 등록된 용어를 우선 표시 | 회사 특화 용어를 정확히 이해하기 위해 | ✅ v2.4.1 신규 |
|
||||
| UFR-TERM-030 | AI | 관리자 | 용어관리 | 관리자로서 | 용어 사전을 등록/수정 | 회사 특화 용어를 관리하기 위해 | ✅ v2.4.1 신규 |
|
||||
|
||||
---
|
||||
|
||||
## 📊 서비스별 유저스토리 개수
|
||||
|
||||
| 서비스 | 개수 | 유저스토리 ID |
|
||||
|---|:---:|---|
|
||||
| **User** | 2 | UFR-USER-010, UFR-USER-020 |
|
||||
| **Meeting** | 16 | UFR-MEET-010, UFR-MEET-015, UFR-MEET-020, UFR-MEET-030, UFR-MEET-040, UFR-MEET-050, UFR-MEET-046, UFR-MEET-047, UFR-MEET-055, UFR-COLLAB-010, UFR-COLLAB-020, UFR-COLLAB-030, UFR-PART-010, UFR-PART-020, UFR-PART-030, UFR-HOST-010, UFR-HOST-020 |
|
||||
| **AI** | 9 | UFR-AI-010, UFR-AI-020, UFR-AI-030, UFR-AI-036, UFR-AI-040, UFR-RAG-010, UFR-RAG-020, UFR-TERM-010, UFR-TERM-020, UFR-TERM-030 |
|
||||
| **STT** | 2 | UFR-STT-010, UFR-STT-020 |
|
||||
| **Notification** | 1 | UFR-NOTI-010 |
|
||||
| **전체** | **32** | - |
|
||||
|
||||
---
|
||||
|
||||
## 👥 역할별 유저스토리 분류
|
||||
|
||||
### 회의 생성자 (Host) - 7개
|
||||
| ID | 제목 | 핵심 기능 |
|
||||
|---|---|---|
|
||||
| UFR-MEET-010 | 회의예약 | 회의 예약 및 참석자 초대 |
|
||||
| UFR-MEET-020 | 템플릿선택 | 회의 템플릿 선택 |
|
||||
| UFR-MEET-030 | 회의시작 | 회의 시작 및 녹음 준비 |
|
||||
| UFR-MEET-040 | 회의종료 | 회의 종료 및 요약 확인 |
|
||||
| UFR-MEET-050 | 최종확정 | 회의록 최종 확정 |
|
||||
| UFR-HOST-010 | 회의종료권한 | 회의 종료 전용 권한 |
|
||||
| UFR-HOST-020 | 녹음제어권한 | 녹음 제어 전용 권한 |
|
||||
|
||||
### 회의 참석자 (Participant) - 19개
|
||||
| ID | 제목 | 핵심 기능 |
|
||||
|---|---|---|
|
||||
| UFR-MEET-015 | 회의진행 중 참석자 초대 | 실시간 참석자 추가 |
|
||||
| UFR-MEET-046 | 회의록목록조회 | 회의록 목록 조회 및 필터링 |
|
||||
| UFR-MEET-047 | 회의록상세조회 | 회의록 상세 정보 조회 |
|
||||
| UFR-MEET-055 | 회의록수정 | 회의록 수정 및 검증 |
|
||||
| UFR-AI-010 | 회의록자동작성 | AI 회의록 자동 작성 |
|
||||
| UFR-AI-020 | Todo자동추출 | AI Todo 자동 추출 |
|
||||
| UFR-AI-030 | 실시간AI제안 | 실시간 AI 주요 내용 제안 |
|
||||
| UFR-AI-036 | AI한줄요약 | AI 한줄 요약 생성 |
|
||||
| UFR-AI-040 | 관련회의록연결 | AI 관련 회의록 자동 연결 |
|
||||
| UFR-STT-010 | 음성녹음인식 | 음성 실시간 녹음 및 인식 |
|
||||
| UFR-RAG-010 | 전문용어감지 | 전문용어 자동 감지 |
|
||||
| UFR-RAG-020 | 맥락기반용어설명 | 맥락 기반 용어 설명 |
|
||||
| UFR-COLLAB-010 | 회의록수정동기화 | 실시간 회의록 동기화 |
|
||||
| UFR-COLLAB-020 | 충돌해결 | 안건별 충돌 방지 |
|
||||
| UFR-COLLAB-030 | 검증완료 | 안건 검증 완료 표시 |
|
||||
| UFR-PART-010 | 회의입장 | 회의 입장 |
|
||||
| UFR-PART-020 | AI기반메모작성 | AI 추천 메모 작성 |
|
||||
| UFR-PART-030 | 회의중도퇴장 | 회의 중도 퇴장 |
|
||||
| UFR-TERM-010 | 용어자동감지 | 용어 자동 감지 및 표시 |
|
||||
| UFR-TERM-020 | 회사용어사전 | 회사 특화 용어 우선 표시 |
|
||||
|
||||
### 관리자 (Admin) - 1개
|
||||
| ID | 제목 | 핵심 기능 |
|
||||
|---|---|---|
|
||||
| UFR-TERM-030 | 용어관리 | 용어 사전 등록/수정 |
|
||||
|
||||
### 시스템 (System) - 3개
|
||||
| ID | 제목 | 핵심 기능 |
|
||||
|---|---|---|
|
||||
| UFR-STT-020 | 텍스트변환 | 음성-텍스트 변환 |
|
||||
| UFR-NOTI-010 | 알림발송 | 이메일 알림 자동 발송 |
|
||||
| UFR-USER-010 | 로그인 | 사용자 인증 |
|
||||
| UFR-USER-020 | 대시보드 | 대시보드 조회 |
|
||||
|
||||
---
|
||||
|
||||
## 🆕 v2.4.1 변경 사항 (2025-10-27)
|
||||
|
||||
### 신규 유저스토리 (8개)
|
||||
|
||||
| ID | 제목 | 분류 | 설명 |
|
||||
|---|---|---|---|
|
||||
| UFR-PART-010 | 회의입장 | 참석자 공통 | 대시보드에서 "참여하기" 버튼으로 회의 입장 |
|
||||
| UFR-PART-020 | AI기반메모작성 | 참석자 공통 | AI 추천 주요 내용을 메모 입력창에 추가 및 편집 |
|
||||
| UFR-PART-030 | 회의중도퇴장 | 참석자 공통 | "나가기" 버튼으로 회의 퇴장 |
|
||||
| UFR-HOST-010 | 회의종료권한 | 생성자 전용 | 생성자만 "회의 종료" 버튼 사용 가능 |
|
||||
| UFR-HOST-020 | 녹음제어권한 | 생성자 전용 | 생성자만 녹음 일시정지/재개/종료 가능 |
|
||||
| UFR-TERM-010 | 용어자동감지 | AI 기능 | AI가 자동으로 감지한 용어를 "용어" 탭에 표시 |
|
||||
| UFR-TERM-020 | 회사용어사전 | AI 기능 | 회사 용어 사전(JSON) 우선 표시 |
|
||||
| UFR-TERM-030 | 용어관리 | 관리 기능 | 관리자가 용어 사전 등록/수정 |
|
||||
|
||||
### 수정된 유저스토리 (3개)
|
||||
|
||||
| ID | 제목 | 수정 내용 |
|
||||
|---|---|---|
|
||||
| UFR-MEET-040 | 회의종료 | 회의 종료 권한을 생성자 전용으로 명확화, "확인 전용" 화면 정책 추가, 3가지 옵션 명확화 (회의록 수정/바로 최종 확정/대시보드) |
|
||||
| UFR-MEET-030 | 회의시작 | 회의 진입 경로 2가지 명시 (바로시작, 참여하기), AI 제안 탭에 개인 메모 작성 영역 추가 (참석자별 독립) |
|
||||
| UFR-AI-040 | 관련회의록연결 | 유사 내용 요약 추가 (최대 3개 추천, 관련도 퍼센트, 3-5문장 요약, 성능 목표 1초 이내) |
|
||||
|
||||
---
|
||||
|
||||
## 🔍 주요 기능별 유저스토리 매핑
|
||||
|
||||
### 회의 생명주기 (Meeting Lifecycle)
|
||||
1. **회의 예약**: UFR-MEET-010
|
||||
2. **템플릿 선택**: UFR-MEET-020
|
||||
3. **회의 시작**: UFR-MEET-030, UFR-PART-010
|
||||
4. **회의 진행**: UFR-STT-010, UFR-AI-010, UFR-AI-030, UFR-PART-020
|
||||
5. **회의 종료**: UFR-MEET-040, UFR-HOST-010
|
||||
6. **회의록 수정**: UFR-MEET-055, UFR-COLLAB-010, UFR-COLLAB-020
|
||||
7. **최종 확정**: UFR-MEET-050, UFR-COLLAB-030
|
||||
|
||||
### AI 기능 (AI Features)
|
||||
- **회의록 자동 작성**: UFR-AI-010
|
||||
- **Todo 자동 추출**: UFR-AI-020
|
||||
- **실시간 AI 제안**: UFR-AI-030
|
||||
- **AI 한줄 요약**: UFR-AI-036
|
||||
- **관련 회의록 연결**: UFR-AI-040
|
||||
- **전문 용어 감지**: UFR-RAG-010, UFR-TERM-010
|
||||
- **맥락 기반 용어 설명**: UFR-RAG-020, UFR-TERM-020
|
||||
|
||||
### 실시간 협업 (Real-time Collaboration)
|
||||
- **참석자 초대**: UFR-MEET-015
|
||||
- **수정 동기화**: UFR-COLLAB-010
|
||||
- **충돌 해결**: UFR-COLLAB-020
|
||||
- **검증 완료**: UFR-COLLAB-030
|
||||
|
||||
### 권한 관리 (Authorization)
|
||||
- **생성자 전용**: UFR-HOST-010, UFR-HOST-020
|
||||
- **참석자 공통**: UFR-PART-010, UFR-PART-020, UFR-PART-030
|
||||
- **관리자 전용**: UFR-TERM-030
|
||||
|
||||
---
|
||||
|
||||
## 📝 유저스토리 작성 규칙
|
||||
|
||||
본 문서의 유저스토리는 다음 형식을 따릅니다:
|
||||
|
||||
```
|
||||
UFR-{SERVICE}-{NUMBER}: [{기능명}] {역할}로서 | 나는, {목적}를 위해 | {행동}을 하고 싶다.
|
||||
```
|
||||
|
||||
### 서비스 코드
|
||||
- **USER**: 사용자 인증 및 대시보드
|
||||
- **MEET**: 회의 및 회의록 관리
|
||||
- **AI**: AI 기반 자동화 기능
|
||||
- **STT**: 음성-텍스트 변환
|
||||
- **RAG**: 벡터 검색 및 맥락 기반 설명
|
||||
- **COLLAB**: 실시간 협업 (Meeting 서비스에 통합)
|
||||
- **NOTI**: 알림 발송
|
||||
- **PART**: 회의 참석자 공통 기능
|
||||
- **HOST**: 회의 생성자 전용 기능
|
||||
- **TERM**: 용어 관리 기능
|
||||
|
||||
---
|
||||
|
||||
## 📌 백로그 및 향후 계획
|
||||
|
||||
### Phase 2 후보 기능
|
||||
- 회의 템플릿 커스터마이징
|
||||
- Todo 대시보드 및 칸반 보드
|
||||
- 회의록 버전 관리 및 변경 이력
|
||||
- 회의 통계 및 분석 대시보드
|
||||
- 다국어 지원 (음성 인식 및 UI)
|
||||
|
||||
---
|
||||
|
||||
## 📚 참고 문서
|
||||
- 유저스토리 원본: [design/userstory.md](./userstory.md)
|
||||
- UI/UX 설계서: [design/uiux/uiux.md](./uiux/uiux.md)
|
||||
- 프로토타입: [design/uiux/prototype/](./uiux/prototype/)
|
||||
+108
-67
@@ -1,10 +1,25 @@
|
||||
# AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.4.0)
|
||||
# AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.4.1)
|
||||
|
||||
- [AI기반 회의록 작성 및 이력 관리 개선 서비스 - 유저스토리 (v2.4.0)](#ai기반-회의록-작성-및-이력-관리-개선-서비스---유저스토리-v240)
|
||||
- [차별화 전략](#차별화-전략)
|
||||
- [1. 기본 기능 (Hygiene Factors)](#1-기본-기능-hygiene-factors)
|
||||
- [2. 핵심 차별화 포인트 (Differentiators)](#2-핵심-차별화-포인트-differentiators)
|
||||
- [마이크로서비스 구성](#마이크로서비스-구성)
|
||||
## 목차
|
||||
- [차별화 전략](#차별화-전략)
|
||||
- [1. 기본 기능 (Hygiene Factors)](#1-기본-기능-hygiene-factors)
|
||||
- [2. 핵심 차별화 포인트 (Differentiators)](#2-핵심-차별화-포인트-differentiators)
|
||||
- [마이크로서비스 구성](#마이크로서비스-구성)
|
||||
- [유저스토리 - USER & MEETING 서비스](#유저스토리---user--meeting-서비스)
|
||||
- [USER 서비스](#user-서비스)
|
||||
- [MEETING 서비스](#meeting-서비스)
|
||||
- [유저스토리 - AI, STT, RAG, COLLAB, NOTIFICATION 서비스](#유저스토리-v230---ai-stt-rag-collab-todo-notification-서비스)
|
||||
- [AI 서비스](#ai-서비스)
|
||||
- [STT 서비스](#stt-서비스)
|
||||
- [RAG 서비스 (AI 서비스에 통합)](#rag-서비스-ai-서비스에-통합)
|
||||
- [COLLAB 서비스 (Meeting 서비스에 통합)](#collab-서비스-meeting-서비스에-통합)
|
||||
- [NOTIFICATION 서비스](#notification-서비스-신규)
|
||||
- [MVP 개선 사항 (v2.3.1)](#mvp-개선-사항-v231)
|
||||
- [회의 참석자 권한 및 기능 단순화](#회의-참석자-권한-및-기능-단순화)
|
||||
- [회의 생성자 전용 기능](#회의-생성자-전용-기능)
|
||||
- [용어 설명 기능 (MVP 단순화)](#용어-설명-기능-mvp-단순화)
|
||||
- [기존 유저스토리 수정](#기존-유저스토리-수정)
|
||||
- [문서 이력](#문서-이력)
|
||||
|
||||
---
|
||||
|
||||
@@ -44,7 +59,7 @@
|
||||
- 업무 이력 통합
|
||||
|
||||
---
|
||||
# 유저스토리 v2.3.0 - USER & MEETING 서비스
|
||||
# 유저스토리 - USER & MEETING 서비스
|
||||
|
||||
## USER 서비스
|
||||
|
||||
@@ -135,25 +150,23 @@
|
||||
2. 회의 제목 입력 (최대 100자)
|
||||
3. 날짜 선택 (오늘 이후 날짜, 달력 UI)
|
||||
4. 시작/종료 시간 선택 (15분 단위 커스텀 시간 선택기)
|
||||
5. (선택) 종일 회의 토글 활성화 시 시간 입력 비활성화
|
||||
6. 온라인/오프라인 회의 선택 (토글)
|
||||
7. 장소 입력 (최대 200자)
|
||||
5. 온라인/오프라인 회의 선택 (토글)
|
||||
6. 장소 입력 (최대 200자)
|
||||
- 오프라인: 예) 본사 2층 대회의실
|
||||
- 온라인: 예) Zoom, Google Meet + 회의 링크 입력 또는 자동 생성
|
||||
8. 참석자 추가 (현재 사용자는 기본 포함)
|
||||
7. 참석자 추가 (현재 사용자는 기본 포함)
|
||||
- "참석자 추가" 버튼 클릭
|
||||
- 검색 모달에서 이름 또는 이메일로 검색
|
||||
- 사용자 선택하여 추가
|
||||
- 칩으로 표시, X 버튼으로 제거 가능 (본인 제외)
|
||||
9. (선택) 안건 입력 (텍스트 영역)
|
||||
10. "임시저장" 버튼 또는 "예약 완료" 버튼 클릭
|
||||
8. (선택) 안건 입력 (텍스트 영역)
|
||||
9. "임시저장" 버튼 또는 "예약 완료" 버튼 클릭
|
||||
|
||||
**입력:**
|
||||
- 회의 제목: 텍스트 입력, 필수, 최대 100자, 문자 카운터 표시
|
||||
- 날짜: date 타입, 필수, 오늘 이후 날짜만 선택 가능, 달력 아이콘(📅) 표시
|
||||
- 시작 시간: 커스텀 시간 선택기 (readonly), 필수, 15분 단위 (00, 15, 30, 45)
|
||||
- 종료 시간: 커스텀 시간 선택기 (readonly), 필수, 15분 단위
|
||||
- 종일 회의: 토글 스위치 (선택)
|
||||
- 온라인 회의: 토글 스위치 (선택)
|
||||
- 장소: 텍스트 입력, 선택, 최대 200자, 문자 카운터 표시
|
||||
- 회의 링크: URL 입력, 선택, 온라인 회의인 경우에만 표시, "자동 생성" 버튼 제공
|
||||
@@ -218,15 +231,18 @@
|
||||
|
||||
### UFR-MEET-020: [템플릿선택] 회의 생성자로서 | 나는, 회의록을 효율적으로 작성하기 위해 | 회의 유형에 맞는 템플릿을 선택하고 싶다.
|
||||
|
||||
**템플릿선택 진입 경로:**
|
||||
- **경로 1**: 대시보드(02-대시보드.html) → "바로시작" FAB 버튼 → 템플릿 선택(04-템플릿선택.html)
|
||||
- **경로 2**: 회의예약 (03-회의예약.html) → 템플릿 선택(04-템플릿선택.html)
|
||||
-
|
||||
**수행절차:**
|
||||
1. 대시보드에서 "바로시작" FAB 버튼 클릭
|
||||
2. 템플릿 선택 화면(04-템플릿선택.html) 표시
|
||||
3. 4가지 템플릿 중 선택 또는 "건너뛰기" 선택
|
||||
1. 위 경로 중 하나를 통해 템플릿 선택 화면(04-템플릿선택.html) 진입
|
||||
2. 4가지 템플릿 중 선택 또는 "건너뛰기" 선택
|
||||
- 일반 회의: 회의 개요, 논의 사항, 결정 사항, 액션 아이템
|
||||
- 스크럼 회의: 어제 한 일, 오늘 할 일, 블로커/이슈
|
||||
- 킥오프 회의: 프로젝트 개요, 목표 및 범위, 역할 및 책임, 일정 및 마일스톤
|
||||
- 주간 회의: 지난주 성과, 이번주 계획, 주요 이슈, 다음 액션
|
||||
4. 선택 완료 시 회의 시작 (05-회의진행.html로 이동)
|
||||
3. 선택 완료 시 회의 시작 (05-회의진행.html로 이동)
|
||||
|
||||
**입력:**
|
||||
- 템플릿 선택: 4가지 중 1개 선택 또는 건너뛰기
|
||||
@@ -242,6 +258,7 @@
|
||||
|
||||
**관련 유저스토리:**
|
||||
- UFR-USER-020: 대시보드 조회
|
||||
- UFR-MEET-010: 회의예약
|
||||
- UFR-MEET-030: 회의시작
|
||||
|
||||
---
|
||||
@@ -260,11 +277,14 @@
|
||||
5. 웨이브폼 애니메이션 표시 (녹음 상태 시각화)
|
||||
6. 탭 네비게이션으로 기능 전환:
|
||||
- 참석자: 참석자 목록 및 실시간 초대
|
||||
- AI 제안: 실시간 AI 분석 결과 및 메모 추가
|
||||
- 용어사전: 자동 추출된 용어 및 검색
|
||||
- 관련회의록: 자동 연결된 이전 회의록
|
||||
7. 회의 메모 작성 (하단 고정 메모 영역)
|
||||
8. 일시정지 또는 회의 종료 버튼 클릭
|
||||
- AI 제안: 실시간 AI 분석 결과 및 개인 메모 작성
|
||||
- AI가 인식한 주요 내용 표시
|
||||
- 참석자별 개인 메모 작성 영역 (수동 저장만 지원)
|
||||
- 용어사전: 실시간 AI 자동 인식된 용어 및 검색
|
||||
- 관련회의록: 실시간 AI 자동 연결된 이전 회의록
|
||||
7. 하단 고정 버튼 (역할별 차별화)
|
||||
- 회의 생성자: [일시정지/녹음재개] + [회의 종료]
|
||||
- 회의 참석자: [회의 나가기]
|
||||
|
||||
**입력:**
|
||||
- 녹음 시작/일시정지: 버튼 클릭
|
||||
@@ -275,16 +295,22 @@
|
||||
- 헤더: 회의 제목, 녹음 상태 (녹음 중/일시정지), 경과 시간
|
||||
- 웨이브폼 애니메이션: 녹음 상태 시각화
|
||||
- 참석자 탭: 참석자 목록, 초대 버튼
|
||||
- AI 제안 탭: AI 분석 카드, "메모에 추가" 버튼
|
||||
- AI 제안 탭:
|
||||
- AI가 인식한 주요 내용 리스트
|
||||
- 개인 메모 작성 영역 (참석자별 독립)
|
||||
- 저장 버튼 (수동 저장만)
|
||||
- 용어사전 탭: 자동 추출된 용어, 검색 기능
|
||||
- 관련회의록 탭: 자동 연결된 이전 회의록 목록
|
||||
- 하단 고정 버튼: 일시정지, 회의 종료
|
||||
- 하단 고정 버튼:
|
||||
- 회의 생성자: [일시정지/녹음재개] + [회의 종료]
|
||||
- 회의 참석자: [회의 나가기]
|
||||
|
||||
**예외처리:**
|
||||
- 녹음 권한 없음: "마이크 권한이 필요합니다" 에러 메시지
|
||||
- 네트워크 오류: "녹음 중 오류가 발생했습니다" 에러 메시지
|
||||
- 일시정지 확인: "일시정지하시겠습니까?" 확인 모달
|
||||
- 종료 확인: "회의를 종료하시겠습니까?" 확인 모달
|
||||
- 회의 종료 확인 (생성자): "회의를 종료하시겠습니까? 모든 참석자의 회의가 종료됩니다" 확인 모달
|
||||
- 회의 나가기 확인 (참석자): "회의에서 나가시겠습니까? 저장하지 않은 메모는 삭제됩니다" 확인 모달
|
||||
|
||||
**관련 유저스토리:**
|
||||
- UFR-MEET-020: 템플릿선택
|
||||
@@ -464,12 +490,30 @@
|
||||
- AI 상세 요약
|
||||
- 관련회의록 링크
|
||||
4. "수정" 버튼 클릭 시 회의록 수정 화면으로 이동
|
||||
5. Todo 리스트 영역 (대시보드 탭):
|
||||
- "추가" 버튼: 모든 참석자에게 노출, 클릭 시 Todo 추가 모달 표시
|
||||
- Todo 항목별 "편집" 버튼: 회의 생성자에게만 노출
|
||||
- Todo 추가 모달: 제목, 담당자, 마감일 입력
|
||||
- Todo 편집 모달: 제목, 마감일 수정 (회의 생성자만 담당자 변경 가능)
|
||||
|
||||
**입력:**
|
||||
- 탭 클릭: 대시보드 / 회의록
|
||||
- Todo 추가 클릭: "추가" 버튼
|
||||
- Todo 편집 클릭: Todo 항목별 "편집(✏️)" 버튼 (회의 생성자만)
|
||||
- Todo 추가/편집 모달 입력:
|
||||
- 제목: 텍스트, 필수
|
||||
- 담당자: 드롭다운 선택, 필수 (추가 시 또는 편집 시 생성자만)
|
||||
- 마감일: 날짜 선택, 필수
|
||||
|
||||
**출력/결과:**
|
||||
- 헤더: 회의 제목, "수정" 버튼 (제목 텍스트 바로 옆에 배치, 권한에 따라 표시)
|
||||
- Todo 리스트 (대시보드 탭):
|
||||
- "추가" 버튼: 모든 참석자에게 표시
|
||||
- Todo 항목별 "편집(✏️)" 버튼: 회의 생성자만 표시
|
||||
- Todo 추가 성공: "Todo가 추가되었습니다" 성공 메시지 → "담당자에게 알림이 전송되었습니다" 정보 메시지 → "캘린더가 업데이트되었습니다" 정보 메시지
|
||||
- Todo 편집 성공: "Todo가 수정되었습니다" 성공 메시지
|
||||
- 담당자 변경 시: "이전 담당자와 새 담당자에게 알림이 전송되었습니다" 정보 메시지
|
||||
- 마감일 변경 시: "캘린더가 업데이트되었습니다" 정보 메시지
|
||||
- 대시보드 탭:
|
||||
- 통계, 키워드, 핵심내용, 결정사항, Todo 진행상황, 관련회의록
|
||||
- Todo 카드: 제목, 담당자, 마감일만 표시 (D-day, 우선순위 라벨 없음)
|
||||
@@ -480,6 +524,18 @@
|
||||
- 회의록 조회 실패: "회의록 조회 중 오류가 발생했습니다" 에러 메시지
|
||||
- Todo 없음: "등록된 Todo가 없습니다" 빈 상태 표시
|
||||
- 관련회의록 없음: "관련 회의록이 없습니다" 빈 상태 표시
|
||||
- Todo 추가/편집 시 필수 입력 누락: "제목/담당자/마감일을 입력해주세요" 에러 메시지
|
||||
- Todo 편집 권한 없음 (일반 참석자): 편집 버튼 미표시
|
||||
|
||||
**Todo 권한 정책 (v2.4.1 신규):**
|
||||
- **Todo 추가**: 모든 회의 참석자 가능
|
||||
- "추가" 버튼 모든 참석자에게 노출
|
||||
- 추가 모달에서 제목, 담당자, 마감일 입력
|
||||
- 담당자는 회의 참석자 중 선택
|
||||
- **Todo 편집**: 회의 생성자만 가능
|
||||
- 편집(✏️) 버튼은 회의 생성자에게만 노출
|
||||
- 편집 모달에서 제목, 담당자, 마감일 수정 가능
|
||||
- 일반 참석자는 편집 버튼이 보이지 않음
|
||||
|
||||
**관련 유저스토리:**
|
||||
- UFR-MEET-046: 회의록목록조회
|
||||
@@ -682,58 +738,42 @@
|
||||
|
||||
---
|
||||
|
||||
### UFR-AI-035: [섹션AI요약] 회의 참석자로서 | 나는, 작성한 섹션 내용을 쉽게 요약하기 위해 | 버튼 클릭으로 AI가 섹션 내용을 요약해주기를 원한다.
|
||||
### UFR-AI-036: [AI한줄요약] 회의 참석자로서 | 나는, 각 안건의 핵심을 빠르게 파악하기 위해 | AI가 생성한 한줄 요약을 확인하고 필요 시 재생성하고 싶다.
|
||||
|
||||
**수행절차:**
|
||||
1. 회의록 수정 화면(11-회의록수정.html)에서 안건 상세 요약 편집
|
||||
2. "재생성" 버튼 클릭
|
||||
3. AI가 해당 안건의 전체 내용 (메모, STT 텍스트) 분석
|
||||
4. 2-3문장 요약 생성 (2-5초 처리)
|
||||
5. 기존 상세 요약 대체
|
||||
|
||||
**시나리오 1: 자동 생성 (회의 종료 시)**
|
||||
1. 회의 종료 시 AI가 각 안건별로 한줄 요약 생성
|
||||
2. 안건 관련 메모 및 STT 텍스트를 분석하여 30자 이내로 핵심 내용 압축
|
||||
3. 회의 종료 화면에 안건별 한줄 요약 표시 (읽기 전용)
|
||||
|
||||
**시나리오 2: 수동 재생성 (회의록 수정 시)**
|
||||
1. 회의록 수정 화면(11-회의록수정.html)에서 안건별 "AI 요약" 영역 확인
|
||||
2. 텍스트 편집 영역에서 안건 내용 수정
|
||||
3. "AI 재생성" 버튼 클릭
|
||||
4. AI가 수정된 텍스트 편집 영역 내용을 분석하여 한줄 요약 생성 (2-5초 처리)
|
||||
5. "AI 요약" 영역에 새로운 한줄 요약 표시
|
||||
6. "재생성되었습니다" 토스트 메시지 표시
|
||||
7. 재생성된 한줄 요약은 회의록 상세조회 화면의 대시보드 및 회의록 탭에 즉시 반영
|
||||
|
||||
**입력:**
|
||||
- 안건 제목
|
||||
- 안건 관련 메모 및 STT 텍스트
|
||||
- 자동 생성: 안건 관련 메모 및 STT 텍스트
|
||||
- 재생성: 텍스트 편집 영역의 안건 내용
|
||||
- 재생성 버튼 클릭 이벤트
|
||||
|
||||
**출력/결과:**
|
||||
- 로딩 상태: "재생성 중..." 표시
|
||||
- 재생성 완료: 새로운 AI 상세 요약 (2-3문장)
|
||||
- 토스트 메시지: "재생성되었습니다"
|
||||
- 자동 저장 트리거
|
||||
|
||||
**예외처리:**
|
||||
- AI 재생성 실패: "재생성 중 오류가 발생했습니다" 에러 메시지
|
||||
- 네트워크 오류: 재시도 로직 또는 기존 요약 유지
|
||||
- 타임아웃: "재생성 시간이 초과되었습니다. 다시 시도해주세요" 안내
|
||||
|
||||
**관련 유저스토리:**
|
||||
- UFR-MEET-055: 회의록수정
|
||||
- UFR-AI-010: 회의록자동작성
|
||||
|
||||
---
|
||||
|
||||
### UFR-AI-036: [AI한줄요약] 회의 참석자로서 | 나는, 각 안건의 핵심을 빠르게 파악하기 위해 | AI가 생성한 편집 불가능한 한줄 요약을 확인하고 싶다.
|
||||
|
||||
**수행절차:**
|
||||
1. 회의 종료 시 AI가 각 안건별로 한줄 요약 생성
|
||||
2. 30자 이내로 핵심 내용 압축
|
||||
3. 회의 종료 화면 및 회의록 수정 화면에 표시
|
||||
4. 읽기 전용 필드로 표시 (편집 불가)
|
||||
5. 회의록 상세 조회 시 안건별로 한줄 요약 표시
|
||||
|
||||
**입력:**
|
||||
- 안건의 AI 상세 요약
|
||||
- 안건 관련 메모 및 STT 텍스트
|
||||
|
||||
**출력/결과:**
|
||||
- AI 한줄 요약 (30자 이내, 읽기 전용)
|
||||
- 회의 종료 화면, 회의록 수정 화면, 회의록 상세 조회 화면에 표시
|
||||
- AI 한줄 요약 (30자 이내)
|
||||
- 회의 종료 화면: 안건별 한줄 요약 (읽기 전용)
|
||||
- 회의록 수정 화면: "AI 요약" 영역에 한줄 요약 표시 및 재생성 기능
|
||||
- 회의록 상세조회 화면: 대시보드 및 회의록 탭에 한줄 요약 표시
|
||||
- 재생성 시: "재생성 중..." 로딩 → 한줄 요약 업데이트 → "재생성되었습니다" 토스트
|
||||
|
||||
**예외처리:**
|
||||
- 한줄 요약 생성 실패: 안건 제목 사용 또는 "요약 없음" 표시
|
||||
- 30자 초과: 자동 트림 처리
|
||||
- AI 재생성 실패: "재생성 중 오류가 발생했습니다" 에러 메시지
|
||||
- 네트워크 오류: 재시도 로직 또는 기존 요약 유지
|
||||
- 타임아웃: "재생성 시간이 초과되었습니다. 다시 시도해주세요" 안내
|
||||
|
||||
**관련 유저스토리:**
|
||||
- UFR-AI-010: 회의록자동작성
|
||||
@@ -1395,7 +1435,8 @@
|
||||
|
||||
| 버전 | 날짜 | 작성자 | 변경 내용 |
|
||||
|------|------|--------|-----------|
|
||||
| v2.4.0 | 2025-10-27 | 팀 전체 | • MVP 스코프 축소: Todo 관리 기능 제거<br>• UFR-USER-020 수정: 대시보드에서 "나의 Todo" 제거, "작성중 회의록" 추가<br>• UFR-PART-020 변경: AI주요내용체크 → AI기반메모작성 (메모 입력창 + AI 추천)<br>• UFR-AI-010 개선: 회의록 생성 시 참석자 메모 참조<br>• UFR-MEET-055 개선: 회의록 수정 시 실시간 협업 제거, 검증완료 체크로 보호<br>• TODO 서비스 전체 제거 (UFR-TODO-010/030/040)<br>• NOTIFICATION 서비스: Todo 관련 알림 제거<br>• 네비게이션 간소화: Todo 관리 메뉴 제거 (대시보드, 회의록만 유지) |
|
||||
| v2.4.1 | 2025-10-27 | 팀 전체 | • UFR-MEET-047 개선: Todo 추가/편집 권한 정책 명확화<br> - Todo 추가: 모든 회의 참석자 가능 ("추가" 버튼 모든 참석자에게 노출)<br> - Todo 편집: 회의 생성자만 가능 (편집 버튼은 생성자에게만 노출)<br> - Todo 추가 모달: 제목, 담당자, 마감일 입력 (모든 참석자)<br> - Todo 편집 모달: 제목, 담당자, 마감일 수정 (생성자만, 바텀시트 스타일)<br>• 프로토타입 UI 개선: 10-회의록상세조회.html<br> - Todo 추가 모달과 편집 모달 바텀시트 스타일 통일<br> - 편집 버튼에 creator-only 클래스 적용하여 권한별 표시/숨김 처리 |
|
||||
| v2.4.0 | 2025-10-27 | 팀 전체 | • MVP 스코프 축소: Todo 관리 기능 제거<br>• AI 요약 기능 통합 및 단순화<br>• UFR-USER-020 수정: 대시보드에서 "나의 Todo" 제거, "작성중 회의록" 추가<br>• UFR-PART-020 변경: AI주요내용체크 → AI기반메모작성 (메모 입력창 + AI 추천)<br>• UFR-AI-010 개선: 회의록 생성 시 참석자 메모 참조<br>• UFR-MEET-055 개선: 회의록 수정 시 실시간 협업 제거, 검증완료 체크로 보호<br> - 프로토타입 UI 개선: 안건별 검증완료 UI 단순화 (참석자: 체크박스만, 생성자: 검증완료 시 잠금해제 버튼)<br>• TODO 서비스 전체 제거 (UFR-TODO-010/030/040)<br>• NOTIFICATION 서비스: Todo 관련 알림 제거<br>• 네비게이션 간소화: Todo 관리 메뉴 제거 (대시보드, 회의록만 유지)<br>• UFR-MEET-030 개선: AI 제안 탭 내 개인 메모 작성 기능 명확화 (수동 저장만), 하단 고정 버튼 역할별 차별화 (생성자: 일시정지/재개+종료, 참석자: 나가기)<br>• UFR-AI-035 삭제: 섹션AI요약 제거 (중복 기능)<br>• UFR-AI-036 개선: AI 한줄요약 확인 및 재생성 기능 통합<br> - 회의 종료 시: 자동 생성 (읽기 전용)<br> - 회의록 수정 시: 텍스트 편집 영역 내용 기반 재생성 기능 추가<br> - "AI 상세요약" → "AI 요약"으로 명칭 변경<br> - 회의록 상세조회 화면의 대시보드 및 회의록 탭에 한줄요약 표시<br> - 프로토타입 UI 개선: AI 재생성 버튼 스타일 통일 (btn-secondary → btn-primary)<br>• UFR-COLLAB-030 개선: 안건 기반 충돌 방지 메커니즘 (검증완료 체크로 보호)|
|
||||
| v2.3.1 | 2025-10-27 | 팀 전체 | • MVP 개선: 회의 참석자 권한 단순화<br>• 신규 유저스토리: UFR-PART-010/020/030 (참석자 공통), UFR-HOST-010/020 (생성자 전용)<br>• 신규 유저스토리: UFR-TERM-010/020/030 (용어 기능 MVP 단순화)<br>• UFR-MEET-040 수정: 회의 종료 권한 생성자 전용으로 명확화<br>• UFR-MEET-030 개선: 회의 진입 경로 2가지 명시 (바로시작, 참여하기)<br>• UFR-AI-040 개선: 관련 회의록 유사 내용 요약 추가 (최대 3개, 퍼센트 표시, 3-5문장 요약)<br>• 메모 기능 단순화: 체크박스 방식으로 변경<br>• 용어 설명 단순화: JSON 용어 사전 방식 도입 |
|
||||
| v2.3.0 | 2025-10-24 | 이미준 | • 프로토타입 분석을 통한 유저스토리 전면 재정비<br>• 신규 유저스토리 추가: UFR-MEET-015 (참석자 실시간 초대), UFR-NOTI-010 (알림 발송)<br>• 알림 아키텍처 폴링 방식으로 통일 (실시간 발송 → 주기적 폴링)<br>• 10개 프로토타입 화면 반영 완료<br>• 마이크로서비스 구성 재정의 (User, Meeting, STT, AI, Notification)<br>• 기존 24개 유저스토리 ID 승계 및 정리 |
|
||||
| v2.2.0 | 2025-10-23 | 이미준 | 이전 버전 |
|
||||
|
||||
+1480
File diff suppressed because it is too large
Load Diff
+1816
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user