- 목록 관리 페이지에 고급 필터링 시스템 추가 - 프로젝트별, 검토상태별, 날짜별 필터링 - 검토 완료/필요 항목 시각적 구분 및 정렬 - 해결 시간 입력 + 확인 버튼으로 검토 완료 처리 - 부적합 조회 페이지에 동일한 필터링 기능 적용 - 검토 상태에 따른 카드 스타일링 (음영 처리) - JavaScript 템플릿 리터럴 오류 수정 - 보고서 페이지 프로젝트별 분석 기능 추가 - 프로젝트 선택 드롭다운 추가 - 총 작업 공수를 프로젝트별 일일공수 데이터로 계산 - 부적합 처리 시간, 카테고리 분석, 상세 목록 모두 프로젝트별 필터링 - localStorage 키 이름 통일 (daily-work-data)
194 lines
9.1 KiB
HTML
194 lines
9.1 KiB
HTML
<!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-plus text-green-500 mr-2"></i>API 프로젝트 생성
|
|
</h1>
|
|
|
|
<div class="space-y-4">
|
|
<div class="p-4 bg-green-50 border border-green-200 rounded-lg">
|
|
<h3 class="font-semibold text-green-800 mb-2">🎯 작업 내용</h3>
|
|
<p class="text-green-700 text-sm">
|
|
백엔드 API를 통해 TKR-25009R M Project를 생성합니다.<br>
|
|
데이터베이스에 실제 프로젝트 레코드가 생성됩니다.
|
|
</p>
|
|
</div>
|
|
|
|
<div id="status" class="space-y-2">
|
|
<!-- 상태 메시지가 여기에 표시됩니다 -->
|
|
</div>
|
|
|
|
<button
|
|
id="createBtn"
|
|
onclick="createProject()"
|
|
class="w-full bg-green-500 text-white py-3 px-4 rounded-lg hover:bg-green-600 transition-colors font-medium"
|
|
>
|
|
<i class="fas fa-plus mr-2"></i>TKR-25009R 프로젝트 생성
|
|
</button>
|
|
|
|
<a href="fix-api-data.html" class="block text-center text-orange-600 hover:text-orange-800 mt-4">
|
|
<i class="fas fa-wrench mr-1"></i>API 데이터 수정 도구로 이동
|
|
</a>
|
|
|
|
<a href="debug-data.html" class="block text-center text-blue-600 hover:text-blue-800 mt-2">
|
|
<i class="fas fa-bug 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 createProject() {
|
|
const btn = document.getElementById('createBtn');
|
|
btn.disabled = true;
|
|
btn.innerHTML = '<i class="fas fa-spinner fa-spin mr-2"></i>생성 중...';
|
|
|
|
try {
|
|
// 1. 기존 프로젝트 확인
|
|
addStatus('기존 프로젝트 확인 중...');
|
|
|
|
let existingProjects = [];
|
|
try {
|
|
existingProjects = await ProjectsAPI.getAll();
|
|
addStatus(`기존 프로젝트 ${existingProjects.length}개 발견`, 'text-blue-600');
|
|
} catch (error) {
|
|
addStatus('기존 프로젝트 조회 실패, 새로 생성합니다.', 'text-yellow-600');
|
|
}
|
|
|
|
// TKR-25009R 프로젝트가 이미 있는지 확인
|
|
const existingMProject = existingProjects.find(p => p.job_no === 'TKR-25009R');
|
|
if (existingMProject) {
|
|
addStatus(`✅ TKR-25009R 프로젝트가 이미 존재합니다 (ID: ${existingMProject.id})`, 'text-green-600');
|
|
|
|
// localStorage 프로젝트 ID 업데이트
|
|
updateLocalStorageProjectId(existingMProject.id);
|
|
|
|
btn.innerHTML = '<i class="fas fa-check mr-2"></i>이미 존재함';
|
|
btn.className = 'w-full bg-blue-500 text-white py-3 px-4 rounded-lg font-medium';
|
|
return;
|
|
}
|
|
|
|
// 2. 새 프로젝트 생성
|
|
addStatus('TKR-25009R 프로젝트 생성 중...');
|
|
|
|
const projectData = {
|
|
job_no: 'TKR-25009R',
|
|
project_name: 'M Project'
|
|
};
|
|
|
|
const newProject = await ProjectsAPI.create(projectData);
|
|
addStatus(`✅ 프로젝트 생성 완료! ID: ${newProject.id}`, 'text-green-600');
|
|
|
|
// 3. localStorage 프로젝트 ID 업데이트
|
|
updateLocalStorageProjectId(newProject.id);
|
|
|
|
// 완료
|
|
addStatus('🎉 프로젝트 생성 및 동기화 완료!', 'text-green-600 font-bold');
|
|
addStatus('이제 API 데이터 수정 도구를 실행하세요.', 'text-blue-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';
|
|
|
|
} catch (error) {
|
|
addStatus(`❌ 오류 발생: ${error.message}`, 'text-red-600');
|
|
btn.disabled = false;
|
|
btn.innerHTML = '<i class="fas fa-redo mr-2"></i>다시 시도';
|
|
}
|
|
}
|
|
|
|
function updateLocalStorageProjectId(apiProjectId) {
|
|
try {
|
|
// localStorage 프로젝트 데이터 업데이트
|
|
const projects = JSON.parse(localStorage.getItem('work-report-projects') || '[]');
|
|
const mProject = projects.find(p => p.jobNo === 'TKR-25009R');
|
|
|
|
if (mProject) {
|
|
const oldId = mProject.id;
|
|
mProject.id = apiProjectId;
|
|
localStorage.setItem('work-report-projects', JSON.stringify(projects));
|
|
addStatus(`localStorage 프로젝트 ID 업데이트: ${oldId} → ${apiProjectId}`, 'text-blue-600');
|
|
|
|
// 일일 공수 데이터도 업데이트
|
|
const dailyWorkData = JSON.parse(localStorage.getItem('daily-work-data') || '[]');
|
|
let updatedCount = 0;
|
|
|
|
dailyWorkData.forEach(dayData => {
|
|
if (dayData.projects) {
|
|
dayData.projects.forEach(project => {
|
|
if (project.projectId == oldId || project.projectId == 1) {
|
|
project.projectId = apiProjectId;
|
|
project.projectName = 'TKR-25009R - M Project';
|
|
updatedCount++;
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
localStorage.setItem('daily-work-data', JSON.stringify(dailyWorkData));
|
|
addStatus(`일일 공수 데이터 ${updatedCount}개 업데이트`, 'text-blue-600');
|
|
|
|
// localStorage 부적합 사항도 업데이트
|
|
const localIssues = JSON.parse(localStorage.getItem('work-report-issues') || '[]');
|
|
let issueUpdatedCount = 0;
|
|
|
|
localIssues.forEach(issue => {
|
|
if (issue.projectId == oldId || issue.projectId == 1 || issue.project_id == oldId || issue.project_id == 1) {
|
|
issue.projectId = apiProjectId;
|
|
issue.project_id = apiProjectId;
|
|
issue.projectName = 'TKR-25009R - M Project';
|
|
issue.project_name = 'TKR-25009R - M Project';
|
|
issueUpdatedCount++;
|
|
}
|
|
});
|
|
|
|
localStorage.setItem('work-report-issues', JSON.stringify(localIssues));
|
|
addStatus(`localStorage 부적합 사항 ${issueUpdatedCount}개 업데이트`, 'text-blue-600');
|
|
}
|
|
} catch (error) {
|
|
addStatus(`localStorage 업데이트 실패: ${error.message}`, 'text-red-600');
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
</html>
|