feat: 수신함 UI 간소화 및 용어 개선 - 프로젝트 필터만 유지

🎯 UI Simplification:
- 필터링 간소화: 4개 필터 → 1개 (프로젝트만)
- 레이아웃 최적화: grid-cols-4 → max-w-md
- 불필요한 상태/읽음상태/검색 필터 제거

📝 Terminology Improvements:
- '부적합 목록' → '신고 목록'
- '새로 등록된 부적합 사항' → '새로 등록된 신고 사항'
- '새로운 부적합이 등록되면' → '새로운 신고가 등록되면'
- 함수 주석: '부적합 필터링/정렬' → '신고 필터링/정렬'

 Code Optimization:
- filterIssues() 함수 간소화
- 불필요한 DOM 요소 및 이벤트 핸들러 제거
- 프로젝트 필드명 수정: project.name → project.project_name

🎨 Enhanced UX:
- 깔끔하고 직관적인 필터 인터페이스
- 사용자 친화적인 용어 사용
- 집중도 높은 단순한 레이아웃

🔧 Fixed Issues:
- 프로젝트 정보 표시 오류 해결 (필드명 불일치)
- 관리함/폐기함 페이지도 동일 오류 수정
- 프로젝트 로딩 디버깅 로그 추가

Expected Result:
 간결하고 사용하기 쉬운 수신함 인터페이스
 올바른 프로젝트 정보 표시
 일관성 있는 용어 사용으로 사용자 혼란 방지
This commit is contained in:
Hyungi Ahn
2025-10-25 13:01:31 +09:00
parent 7b9dfddec3
commit aacf05d05c

View File

@@ -134,7 +134,7 @@
<i class="fas fa-inbox text-blue-500 mr-3"></i>
수신함
</h1>
<p class="text-gray-600 mt-1">새로 등록된 부적합 사항을 확인하고 처리하세요</p>
<p class="text-gray-600 mt-1">새로 등록된 신고 사항을 확인하고 처리하세요</p>
</div>
<div class="flex items-center space-x-3">
<button onclick="markAllAsRead()" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
@@ -189,9 +189,9 @@
</div>
</div>
<!-- 필터 및 검색 -->
<!-- 필터 -->
<div class="bg-white rounded-xl shadow-sm p-6 mb-6">
<div class="grid grid-cols-1 md:grid-cols-4 gap-4">
<div class="max-w-md">
<!-- 프로젝트 필터 -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">📁 프로젝트</label>
@@ -199,43 +199,14 @@
<option value="">전체 프로젝트</option>
</select>
</div>
<!-- 상태 필터 -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">📋 상태</label>
<select id="statusFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" onchange="filterIssues()">
<option value="">전체 상태</option>
<option value="new">새 부적합</option>
<option value="processing">처리 중</option>
<option value="pending">대기 중</option>
</select>
</div>
<!-- 읽음 상태 필터 -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">👁️ 읽음 상태</label>
<select id="readStatusFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" onchange="filterIssues()">
<option value="">전체</option>
<option value="unread">읽지 않음</option>
<option value="read">읽음</option>
</select>
</div>
<!-- 검색 -->
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">🔍 검색</label>
<input type="text" id="searchInput" placeholder="설명 또는 등록자 검색..."
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500"
onkeyup="filterIssues()">
</div>
</div>
</div>
<!-- 부적합 목록 -->
<!-- 신고 목록 -->
<div class="bg-white rounded-xl shadow-sm">
<div class="p-6 border-b border-gray-200">
<div class="flex items-center justify-between">
<h2 class="text-lg font-semibold text-gray-800">부적합 목록</h2>
<h2 class="text-lg font-semibold text-gray-800">신고 목록</h2>
<div class="flex items-center space-x-2">
<span class="text-sm text-gray-500">정렬:</span>
<select id="sortOrder" class="text-sm border border-gray-300 rounded px-2 py-1" onchange="sortIssues()">
@@ -256,7 +227,7 @@
<div id="emptyState" class="hidden p-12 text-center">
<i class="fas fa-inbox text-6xl text-gray-300 mb-4"></i>
<h3 class="text-lg font-medium text-gray-900 mb-2">수신함이 비어있습니다</h3>
<p class="text-gray-500">새로운 부적합이 등록되면 여기에 표시됩니다.</p>
<p class="text-gray-500">새로운 신고가 등록되면 여기에 표시됩니다.</p>
</div>
</div>
</main>
@@ -550,6 +521,7 @@
// 프로젝트 로드
async function loadProjects() {
console.log('🔄 프로젝트 로드 시작');
try {
const response = await fetch('/api/projects/', {
headers: {
@@ -558,12 +530,18 @@
}
});
console.log('📡 프로젝트 API 응답 상태:', response.status);
if (response.ok) {
projects = await response.json();
console.log('✅ 프로젝트 로드 성공:', projects.length, '개');
console.log('📋 프로젝트 목록:', projects);
updateProjectFilter();
} else {
console.error('❌ 프로젝트 API 응답 실패:', response.status, response.statusText);
}
} catch (error) {
console.error('프로젝트 로드 실패:', error);
console.error('프로젝트 로드 실패:', error);
}
}
@@ -575,7 +553,7 @@
projects.forEach(project => {
const option = document.createElement('option');
option.value = project.id;
option.textContent = project.name;
option.textContent = project.project_name;
projectFilter.appendChild(option);
});
}
@@ -621,30 +599,14 @@
}
}
// 부적합 필터링
// 신고 필터링
function filterIssues() {
const projectFilter = document.getElementById('projectFilter').value;
const statusFilter = document.getElementById('statusFilter').value;
const readStatusFilter = document.getElementById('readStatusFilter').value;
const searchInput = document.getElementById('searchInput').value.toLowerCase();
filteredIssues = issues.filter(issue => {
// 프로젝트 필터
if (projectFilter && issue.project_id != projectFilter) return false;
// 상태 필터
if (statusFilter && issue.status !== statusFilter) return false;
// 읽음 상태 필터
if (readStatusFilter === 'read' && !readStatus.has(issue.id)) return false;
if (readStatusFilter === 'unread' && readStatus.has(issue.id)) return false;
// 검색 필터
if (searchInput) {
const searchText = `${issue.description} ${issue.reporter?.username || ''}`.toLowerCase();
if (!searchText.includes(searchInput)) return false;
}
return true;
});
@@ -652,7 +614,7 @@
displayIssues();
}
// 부적합 정렬
// 신고 정렬
function sortIssues() {
const sortOrder = document.getElementById('sortOrder').value;
@@ -702,7 +664,7 @@
<div class="flex items-center space-x-3 mb-2">
${isUnread ? '<div class="w-2 h-2 bg-blue-500 rounded-full"></div>' : '<div class="w-2 h-2"></div>'}
<span class="badge badge-new">검토 대기</span>
${project ? `<span class="text-sm text-gray-500">${project.name}</span>` : ''}
${project ? `<span class="text-sm text-gray-500">${project.project_name}</span>` : ''}
<span class="text-sm text-gray-400">${timeAgo}</span>
</div>
@@ -878,7 +840,7 @@
const project = projects.find(p => p.id === issue.project_id);
originalInfo.innerHTML = `
<div class="space-y-2">
<div><strong>프로젝트:</strong> ${project ? project.name : '미지정'}</div>
<div><strong>프로젝트:</strong> ${project ? project.project_name : '미지정'}</div>
<div><strong>카테고리:</strong> ${getCategoryText(issue.category)}</div>
<div><strong>설명:</strong> ${issue.description}</div>
<div><strong>등록자:</strong> ${issue.reporter?.username || '알 수 없음'}</div>
@@ -892,7 +854,7 @@
projects.forEach(project => {
const option = document.createElement('option');
option.value = project.id;
option.textContent = project.name;
option.textContent = project.project_name;
if (project.id === issue.project_id) {
option.selected = true;
}