feat: 관리함 개선 - 데이터 필터링 및 탭 구조 개선
📊 Data Filtering Improvements: - 관리함에서 수신함에서 처리된 항목만 표시 (in_progress, completed) - 수신함의 pending_review, disposed 상태 제외 - 올바른 워크플로우 데이터만 관리함에서 처리 🎨 UI Simplification: - 복잡한 필터 제거 (상태, 우선순위, 담당자, 검색) - 프로젝트 필터만 유지하여 핵심 기능에 집중 - 더 깔끔하고 직관적인 인터페이스 📋 Status Tabs Implementation: - 프로젝트 선택 아래에 진행 중/완료됨 탭 추가 - 탭 클릭으로 상태별 이슈 분리 표시 - 진행 중(파란색), 완료됨(초록색) 시각적 구분 - 부드러운 전환 애니메이션 적용 🔧 JavaScript Logic Updates: - currentTab 변수로 현재 선택된 탭 상태 관리 - switchTab() 함수로 탭 전환 및 스타일 업데이트 - filterIssues() 함수에서 review_status 기반 필터링 - 불필요한 필터링 로직 제거로 성능 개선 🚀 User Experience: - 프로젝트 선택 → 상태 탭 선택으로 단순한 워크플로우 - 진행 중과 완료됨 항목을 명확히 분리 - 관리함 본연의 목적에 맞는 기능 집중 Expected Result: ✅ 수신함에서 처리된 항목만 관리함에 표시 ✅ 프로젝트별 진행 중/완료됨 탭으로 분리 ✅ 불필요한 필터 제거로 단순화된 UI ✅ 직관적인 탭 기반 상태 관리
This commit is contained in:
@@ -145,55 +145,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 필터 및 검색 -->
|
<!-- 프로젝트 필터 및 상태 탭 -->
|
||||||
<div class="bg-white rounded-xl shadow-sm p-6 mb-6">
|
<div class="bg-white rounded-xl shadow-sm p-6 mb-6">
|
||||||
<div class="grid grid-cols-1 md:grid-cols-5 gap-4">
|
<div class="space-y-4">
|
||||||
<!-- 프로젝트 필터 -->
|
<!-- 프로젝트 선택 -->
|
||||||
<div>
|
<div class="max-w-md">
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-2">📁 프로젝트</label>
|
<label class="block text-sm font-medium text-gray-700 mb-2">📁 프로젝트</label>
|
||||||
<select id="projectFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500" onchange="filterIssues()">
|
<select id="projectFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500" onchange="filterIssues()">
|
||||||
<option value="">전체 프로젝트</option>
|
<option value="">전체 프로젝트</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 상태 필터 -->
|
<!-- 상태 탭 -->
|
||||||
<div>
|
<div class="flex space-x-1 bg-gray-100 p-1 rounded-lg max-w-md">
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-2">📋 상태</label>
|
<button id="inProgressTab"
|
||||||
<select id="statusFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500" onchange="filterIssues()">
|
class="flex-1 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200 bg-blue-500 text-white"
|
||||||
<option value="">전체 상태</option>
|
onclick="switchTab('in_progress')">
|
||||||
<option value="new">새 부적합</option>
|
<i class="fas fa-cog mr-2"></i>진행 중
|
||||||
<option value="processing">처리 중</option>
|
</button>
|
||||||
<option value="pending">대기 중</option>
|
<button id="completedTab"
|
||||||
<option value="completed">완료</option>
|
class="flex-1 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200 text-gray-600 hover:text-gray-900"
|
||||||
</select>
|
onclick="switchTab('completed')">
|
||||||
</div>
|
<i class="fas fa-check-circle mr-2"></i>완료됨
|
||||||
|
</button>
|
||||||
<!-- 우선순위 필터 -->
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-2">⚡ 우선순위</label>
|
|
||||||
<select id="priorityFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500" onchange="filterIssues()">
|
|
||||||
<option value="">전체</option>
|
|
||||||
<option value="high">높음</option>
|
|
||||||
<option value="medium">보통</option>
|
|
||||||
<option value="low">낮음</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- 담당자 필터 -->
|
|
||||||
<div>
|
|
||||||
<label class="block text-sm font-medium text-gray-700 mb-2">👤 담당자</label>
|
|
||||||
<select id="assigneeFilter" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-green-500 focus:border-green-500" onchange="filterIssues()">
|
|
||||||
<option value="">전체 담당자</option>
|
|
||||||
<option value="unassigned">미배정</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-green-500 focus:border-green-500"
|
|
||||||
onkeyup="filterIssues()">
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -283,6 +257,7 @@
|
|||||||
let filteredIssues = [];
|
let filteredIssues = [];
|
||||||
let selectedIssues = new Set();
|
let selectedIssues = new Set();
|
||||||
let currentIssueId = null;
|
let currentIssueId = null;
|
||||||
|
let currentTab = 'in_progress'; // 기본값: 진행 중
|
||||||
|
|
||||||
// API 로드 후 초기화 함수
|
// API 로드 후 초기화 함수
|
||||||
async function initializeManagement() {
|
async function initializeManagement() {
|
||||||
@@ -343,12 +318,7 @@
|
|||||||
// 부적합 목록 로드 (관리자는 모든 부적합 조회)
|
// 부적합 목록 로드 (관리자는 모든 부적합 조회)
|
||||||
async function loadIssues() {
|
async function loadIssues() {
|
||||||
try {
|
try {
|
||||||
let endpoint = '/api/issues/';
|
let endpoint = '/api/issues/admin/all';
|
||||||
|
|
||||||
// 관리자인 경우 전체 부적합 조회 API 사용
|
|
||||||
if (currentUser.role === 'admin') {
|
|
||||||
endpoint = '/api/issues/admin/all';
|
|
||||||
}
|
|
||||||
|
|
||||||
const response = await fetch(endpoint, {
|
const response = await fetch(endpoint, {
|
||||||
headers: {
|
headers: {
|
||||||
@@ -358,7 +328,11 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
issues = await response.json();
|
const allIssues = await response.json();
|
||||||
|
// 관리함에서는 진행 중(in_progress)과 완료됨(completed) 상태만 표시
|
||||||
|
issues = allIssues.filter(issue =>
|
||||||
|
issue.review_status === 'in_progress' || issue.review_status === 'completed'
|
||||||
|
);
|
||||||
filterIssues();
|
filterIssues();
|
||||||
updateStatistics();
|
updateStatistics();
|
||||||
} else {
|
} else {
|
||||||
@@ -370,25 +344,35 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 탭 전환 함수
|
||||||
|
function switchTab(tab) {
|
||||||
|
currentTab = tab;
|
||||||
|
|
||||||
|
// 탭 버튼 스타일 업데이트
|
||||||
|
const inProgressTab = document.getElementById('inProgressTab');
|
||||||
|
const completedTab = document.getElementById('completedTab');
|
||||||
|
|
||||||
|
if (tab === 'in_progress') {
|
||||||
|
inProgressTab.className = 'flex-1 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200 bg-blue-500 text-white';
|
||||||
|
completedTab.className = 'flex-1 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200 text-gray-600 hover:text-gray-900';
|
||||||
|
} else {
|
||||||
|
inProgressTab.className = 'flex-1 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200 text-gray-600 hover:text-gray-900';
|
||||||
|
completedTab.className = 'flex-1 px-4 py-2 text-sm font-medium rounded-md transition-colors duration-200 bg-green-500 text-white';
|
||||||
|
}
|
||||||
|
|
||||||
|
filterIssues();
|
||||||
|
}
|
||||||
|
|
||||||
// 필터링 및 표시 함수들
|
// 필터링 및 표시 함수들
|
||||||
function filterIssues() {
|
function filterIssues() {
|
||||||
const projectFilter = document.getElementById('projectFilter').value;
|
const projectFilter = document.getElementById('projectFilter').value;
|
||||||
const statusFilter = document.getElementById('statusFilter').value;
|
|
||||||
const priorityFilter = document.getElementById('priorityFilter').value;
|
|
||||||
const assigneeFilter = document.getElementById('assigneeFilter').value;
|
|
||||||
const searchInput = document.getElementById('searchInput').value.toLowerCase();
|
|
||||||
|
|
||||||
filteredIssues = issues.filter(issue => {
|
filteredIssues = issues.filter(issue => {
|
||||||
if (projectFilter && issue.project_id != projectFilter) return false;
|
// 현재 탭에 따른 상태 필터링
|
||||||
if (statusFilter && issue.status !== statusFilter) return false;
|
if (issue.review_status !== currentTab) return false;
|
||||||
if (priorityFilter && issue.priority !== priorityFilter) return false;
|
|
||||||
if (assigneeFilter === 'unassigned' && issue.assignee_id) return false;
|
|
||||||
if (assigneeFilter && assigneeFilter !== 'unassigned' && issue.assignee_id != assigneeFilter) return false;
|
|
||||||
|
|
||||||
if (searchInput) {
|
// 프로젝트 필터링
|
||||||
const searchText = `${issue.description} ${issue.reporter?.username || ''}`.toLowerCase();
|
if (projectFilter && issue.project_id != projectFilter) return false;
|
||||||
if (!searchText.includes(searchInput)) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user