feat: 목록 관리 및 보고서 페이지 개선
- 목록 관리 페이지에 고급 필터링 시스템 추가 - 프로젝트별, 검토상태별, 날짜별 필터링 - 검토 완료/필요 항목 시각적 구분 및 정렬 - 해결 시간 입력 + 확인 버튼으로 검토 완료 처리 - 부적합 조회 페이지에 동일한 필터링 기능 적용 - 검토 상태에 따른 카드 스타일링 (음영 처리) - JavaScript 템플릿 리터럴 오류 수정 - 보고서 페이지 프로젝트별 분석 기능 추가 - 프로젝트 선택 드롭다운 추가 - 총 작업 공수를 프로젝트별 일일공수 데이터로 계산 - 부적합 처리 시간, 카테고리 분석, 상세 목록 모두 프로젝트별 필터링 - localStorage 키 이름 통일 (daily-work-data)
This commit is contained in:
171
frontend/fix-api-data.html
Normal file
171
frontend/fix-api-data.html
Normal file
@@ -0,0 +1,171 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ko">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>API 데이터 수정 - M Project</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||
<script src="/static/js/api.js?v=20250917"></script>
|
||||
</head>
|
||||
<body class="bg-gray-50">
|
||||
<div class="container mx-auto px-4 py-8 max-w-2xl">
|
||||
<div class="bg-white rounded-xl shadow-sm p-6">
|
||||
<h1 class="text-2xl font-bold text-gray-800 mb-6">
|
||||
<i class="fas fa-wrench text-orange-500 mr-2"></i>API 데이터 수정
|
||||
</h1>
|
||||
|
||||
<div class="space-y-4">
|
||||
<div class="p-4 bg-yellow-50 border border-yellow-200 rounded-lg">
|
||||
<h3 class="font-semibold text-yellow-800 mb-2">⚠️ 주의사항</h3>
|
||||
<p class="text-yellow-700 text-sm">
|
||||
이 작업은 API 데이터베이스의 모든 부적합 사항에 TKR-25009R 프로젝트 정보를 추가합니다.<br>
|
||||
관리자(hyungi) 계정으로 로그인한 상태에서만 실행하세요.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="status" class="space-y-2">
|
||||
<!-- 상태 메시지가 여기에 표시됩니다 -->
|
||||
</div>
|
||||
|
||||
<button
|
||||
id="fixBtn"
|
||||
onclick="fixApiData()"
|
||||
class="w-full bg-orange-500 text-white py-3 px-4 rounded-lg hover:bg-orange-600 transition-colors font-medium"
|
||||
>
|
||||
<i class="fas fa-tools mr-2"></i>API 데이터 수정 시작
|
||||
</button>
|
||||
|
||||
<a href="debug-data.html" class="block text-center text-blue-600 hover:text-blue-800 mt-4">
|
||||
<i class="fas fa-bug mr-1"></i>디버그 도구로 이동
|
||||
</a>
|
||||
|
||||
<a href="index.html" class="block text-center text-gray-600 hover:text-gray-800 mt-2">
|
||||
<i class="fas fa-arrow-left mr-1"></i>메인으로 돌아가기
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
let currentUser = null;
|
||||
|
||||
// 페이지 로드 시 사용자 확인
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const user = TokenManager.getUser();
|
||||
if (!user) {
|
||||
alert('로그인이 필요합니다.');
|
||||
window.location.href = 'index.html';
|
||||
return;
|
||||
}
|
||||
|
||||
currentUser = user;
|
||||
|
||||
if (currentUser.role !== 'admin') {
|
||||
alert('관리자만 접근 가능합니다.');
|
||||
window.location.href = 'index.html';
|
||||
return;
|
||||
}
|
||||
|
||||
addStatus('✅ 관리자 권한 확인됨', 'text-green-600');
|
||||
});
|
||||
|
||||
function addStatus(message, className = 'text-gray-600') {
|
||||
const statusDiv = document.getElementById('status');
|
||||
const p = document.createElement('p');
|
||||
p.className = `text-sm ${className}`;
|
||||
p.innerHTML = `<i class="fas fa-info-circle mr-2"></i>${message}`;
|
||||
statusDiv.appendChild(p);
|
||||
}
|
||||
|
||||
async function fixApiData() {
|
||||
const btn = document.getElementById('fixBtn');
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>수정 중...';
|
||||
|
||||
try {
|
||||
// 1. TKR-25009R 프로젝트 찾기
|
||||
const projects = JSON.parse(localStorage.getItem('work-report-projects') || '[]');
|
||||
const mProject = projects.find(p => p.jobNo === 'TKR-25009R');
|
||||
|
||||
if (!mProject) {
|
||||
throw new Error('TKR-25009R 프로젝트를 찾을 수 없습니다. 먼저 마이그레이션을 실행하세요.');
|
||||
}
|
||||
|
||||
addStatus(`TKR-25009R 프로젝트 발견 (ID: ${mProject.id})`, 'text-blue-600');
|
||||
|
||||
// 2. API에서 모든 부적합 사항 가져오기
|
||||
addStatus('API에서 부적합 사항 조회 중...');
|
||||
const issues = await IssuesAPI.getAll();
|
||||
addStatus(`총 ${issues.length}개 부적합 사항 발견`, 'text-blue-600');
|
||||
|
||||
// 3. project_id가 null인 부적합 사항들 찾기
|
||||
const issuesWithoutProject = issues.filter(issue => !issue.project_id);
|
||||
addStatus(`프로젝트 정보가 없는 부적합 사항: ${issuesWithoutProject.length}개`, 'text-yellow-600');
|
||||
|
||||
if (issuesWithoutProject.length === 0) {
|
||||
addStatus('✅ 모든 부적합 사항에 이미 프로젝트 정보가 있습니다.', 'text-green-600');
|
||||
btn.innerHTML = '<i class="fas fa-check mr-2"></i>완료';
|
||||
btn.className = 'w-full bg-green-500 text-white py-3 px-4 rounded-lg font-medium';
|
||||
return;
|
||||
}
|
||||
|
||||
// 4. 각 부적합 사항 업데이트
|
||||
let successCount = 0;
|
||||
let errorCount = 0;
|
||||
|
||||
for (let i = 0; i < issuesWithoutProject.length; i++) {
|
||||
const issue = issuesWithoutProject[i];
|
||||
|
||||
try {
|
||||
addStatus(`${i + 1}/${issuesWithoutProject.length}: 부적합 사항 ID ${issue.id} 업데이트 중...`);
|
||||
|
||||
await IssuesAPI.update(issue.id, {
|
||||
project_id: mProject.id
|
||||
});
|
||||
|
||||
successCount++;
|
||||
|
||||
// UI 업데이트를 위한 짧은 대기
|
||||
if (i % 5 === 0) {
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error(`부적합 사항 ID ${issue.id} 업데이트 실패:`, error);
|
||||
addStatus(`❌ 부적합 사항 ID ${issue.id} 업데이트 실패: ${error.message}`, 'text-red-600');
|
||||
errorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
// 5. 결과 표시
|
||||
if (successCount > 0) {
|
||||
addStatus(`✅ ${successCount}개 부적합 사항 업데이트 완료!`, 'text-green-600 font-bold');
|
||||
}
|
||||
|
||||
if (errorCount > 0) {
|
||||
addStatus(`❌ ${errorCount}개 부적합 사항 업데이트 실패`, 'text-red-600');
|
||||
}
|
||||
|
||||
// 6. 완료 처리
|
||||
if (errorCount === 0) {
|
||||
btn.innerHTML = '<i class="fas fa-check mr-2"></i>모든 업데이트 완료';
|
||||
btn.className = 'w-full bg-green-500 text-white py-3 px-4 rounded-lg font-medium';
|
||||
|
||||
addStatus('🎉 모든 API 데이터 수정이 완료되었습니다!', 'text-green-600 font-bold');
|
||||
addStatus('이제 부적합 조회에서 프로젝트 필터가 정상 작동합니다.', 'text-blue-600');
|
||||
} else {
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="fas fa-redo mr-2"></i>다시 시도';
|
||||
btn.className = 'w-full bg-orange-500 text-white py-3 px-4 rounded-lg hover:bg-orange-600 transition-colors font-medium';
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
addStatus(`❌ 오류 발생: ${error.message}`, 'text-red-600');
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="fas fa-redo mr-2"></i>다시 시도';
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user