feat: 관리함 진행 중 페이지 완료 대기 상태 관리 시스템 구현
🎯 상태별 UI 개선: - 진행 중: 파란색 (일반 상태) - 긴급: 주황색 (마감 3일 이내) - 지연됨: 빨간색 (마감일 초과) - 완료 대기: 보라색 (완료 신청 후) 🔒 완료 대기 상태 제한: - 모든 입력 필드 비활성화 (readonly/disabled) - 상세 내용 수정 버튼 → '완료 대기 중' 표시 - 저장 버튼 제거 - 회색 배경으로 비활성화 표시 📋 완료 대기 상태 정보 표시: - 완료 신청 정보 섹션 추가 - 완료 사진, 코멘트, 신청일시 표시 - 보라색 테마로 구분 🔧 3단계 버튼 시스템: 1. 수정: 완료 대기 상태 해제 → 수정 모드 전환 2. 반려: 완료 신청 반려 + 사유 입력 3. 확인: 모든 정보 확인 모달 → 최종 완료 처리 📊 완료 확인 모달: - 기본 정보 (프로젝트, 부적합명, 상세내용, 원인분류) - 관리 정보 (해결방안, 담당부서/자, 조치예상일) - 완료 신청 정보 (완료 사진, 코멘트, 신청일시) - 업로드 사진 (원본 사진 1, 2) - 최종 확인 버튼 🔄 API 엔드포인트 (구현 예정): - POST /api/issues/{id}/reset-completion (수정 모드 전환) - POST /api/issues/{id}/reject-completion (반려 처리) - POST /api/issues/{id}/final-completion (최종 완료) 💡 사용자 경험: - 상태별 색상 코딩으로 직관적 구분 - 완료 대기 시 수정 불가 명확 표시 - 모든 정보 한눈에 확인 가능한 모달 - 단계별 승인 프로세스 Expected Result: ✅ 완료 대기 상태 시각적 구분 ✅ 수정 기능 적절한 제한 ✅ 체계적인 완료 승인 프로세스 ✅ 관리자 친화적 인터페이스
This commit is contained in:
@@ -708,6 +708,44 @@
|
||||
|
||||
// 진행 중 카드 생성
|
||||
function createInProgressRow(issue, project) {
|
||||
// 상태 판별
|
||||
const isPendingCompletion = issue.completion_requested_at;
|
||||
const isOverdue = issue.expected_completion_date && new Date(issue.expected_completion_date) < new Date();
|
||||
const isUrgent = issue.expected_completion_date &&
|
||||
(new Date(issue.expected_completion_date) - new Date()) / (1000 * 60 * 60 * 24) <= 3 &&
|
||||
!isOverdue;
|
||||
|
||||
// 상태 설정
|
||||
let statusConfig = {
|
||||
text: '진행 중',
|
||||
bgColor: 'bg-gradient-to-r from-blue-500 to-blue-600',
|
||||
icon: 'fas fa-cog fa-spin',
|
||||
dotColor: 'bg-white'
|
||||
};
|
||||
|
||||
if (isPendingCompletion) {
|
||||
statusConfig = {
|
||||
text: '완료 대기',
|
||||
bgColor: 'bg-gradient-to-r from-purple-500 to-purple-600',
|
||||
icon: 'fas fa-hourglass-half',
|
||||
dotColor: 'bg-white'
|
||||
};
|
||||
} else if (isOverdue) {
|
||||
statusConfig = {
|
||||
text: '지연됨',
|
||||
bgColor: 'bg-gradient-to-r from-red-500 to-red-600',
|
||||
icon: 'fas fa-clock',
|
||||
dotColor: 'bg-white'
|
||||
};
|
||||
} else if (isUrgent) {
|
||||
statusConfig = {
|
||||
text: '긴급',
|
||||
bgColor: 'bg-gradient-to-r from-orange-500 to-orange-600',
|
||||
icon: 'fas fa-exclamation-triangle',
|
||||
dotColor: 'bg-white'
|
||||
};
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="issue-card bg-white border border-gray-200 rounded-xl p-6 mb-4 shadow-sm hover:shadow-md transition-shadow" data-issue-id="${issue.id}">
|
||||
<!-- 카드 헤더 -->
|
||||
@@ -719,18 +757,38 @@
|
||||
<div class="w-2 h-2 bg-blue-500 rounded-full animate-pulse"></div>
|
||||
</div>
|
||||
<span class="text-sm text-gray-600">${project ? project.project_name : '프로젝트 미지정'}</span>
|
||||
<!-- 상태 표시 -->
|
||||
<div class="flex items-center space-x-2 ${statusConfig.bgColor} text-white px-3 py-1 rounded-full shadow-sm">
|
||||
<div class="w-1.5 h-1.5 ${statusConfig.dotColor} rounded-full animate-pulse"></div>
|
||||
<span class="text-xs font-bold">${statusConfig.text}</span>
|
||||
<i class="${statusConfig.icon} text-xs"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="bg-blue-50 px-3 py-2 rounded-lg border-l-4 border-blue-400">
|
||||
<h3 class="text-lg font-bold text-blue-900">${getIssueTitle(issue)}</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex space-x-2">
|
||||
<button onclick="saveIssueChanges(${issue.id})" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
|
||||
<i class="fas fa-save mr-1"></i>저장
|
||||
</button>
|
||||
<button onclick="completeIssue(${issue.id})" class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors">
|
||||
<i class="fas fa-check mr-1"></i>완료처리
|
||||
</button>
|
||||
${isPendingCompletion ? `
|
||||
<!-- 완료 대기 상태 버튼들 -->
|
||||
<button onclick="editIssue(${issue.id})" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
|
||||
<i class="fas fa-edit mr-1"></i>수정
|
||||
</button>
|
||||
<button onclick="rejectCompletion(${issue.id})" class="px-4 py-2 bg-red-500 text-white rounded-lg hover:bg-red-600 transition-colors">
|
||||
<i class="fas fa-times mr-1"></i>반려
|
||||
</button>
|
||||
<button onclick="confirmCompletion(${issue.id})" class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors">
|
||||
<i class="fas fa-check-circle mr-1"></i>확인
|
||||
</button>
|
||||
` : `
|
||||
<!-- 일반 진행 중 상태 버튼들 -->
|
||||
<button onclick="saveIssueChanges(${issue.id})" class="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors">
|
||||
<i class="fas fa-save mr-1"></i>저장
|
||||
</button>
|
||||
<button onclick="completeIssue(${issue.id})" class="px-4 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors">
|
||||
<i class="fas fa-check mr-1"></i>완료처리
|
||||
</button>
|
||||
`}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -744,9 +802,15 @@
|
||||
<i class="fas fa-align-left text-gray-500 mr-2"></i>
|
||||
<label class="text-sm font-medium text-gray-700">상세 내용</label>
|
||||
</div>
|
||||
<button onclick="toggleDetailEdit(${issue.id})" class="text-xs text-blue-600 hover:text-blue-800 px-2 py-1 rounded border border-blue-200 hover:bg-blue-50 transition-colors">
|
||||
<i class="fas fa-edit mr-1"></i>수정
|
||||
</button>
|
||||
${!isPendingCompletion ? `
|
||||
<button onclick="toggleDetailEdit(${issue.id})" class="text-xs text-blue-600 hover:text-blue-800 px-2 py-1 rounded border border-blue-200 hover:bg-blue-50 transition-colors">
|
||||
<i class="fas fa-edit mr-1"></i>수정
|
||||
</button>
|
||||
` : `
|
||||
<span class="text-xs text-gray-400 px-2 py-1 rounded border border-gray-200 bg-gray-50">
|
||||
<i class="fas fa-lock mr-1"></i>완료 대기 중
|
||||
</span>
|
||||
`}
|
||||
</div>
|
||||
<div id="detail-display-${issue.id}" class="p-3 bg-gray-50 rounded-lg border border-gray-200 min-h-[80px]">
|
||||
<div class="text-gray-600 text-sm leading-relaxed italic">
|
||||
@@ -793,7 +857,7 @@
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||||
<i class="fas fa-lightbulb text-yellow-500 mr-1"></i>해결방안
|
||||
</label>
|
||||
<textarea id="solution_${issue.id}" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none" placeholder="해결 방안을 입력하세요...">${issue.solution || ''}</textarea>
|
||||
<textarea id="solution_${issue.id}" rows="3" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 resize-none ${isPendingCompletion ? 'bg-gray-100 cursor-not-allowed' : ''}" placeholder="해결 방안을 입력하세요..." ${isPendingCompletion ? 'readonly' : ''}>${issue.solution || ''}</textarea>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||
@@ -801,7 +865,7 @@
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||||
<i class="fas fa-building text-blue-500 mr-1"></i>담당부서
|
||||
</label>
|
||||
<select id="responsible_department_${issue.id}" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500">
|
||||
<select id="responsible_department_${issue.id}" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${isPendingCompletion ? 'bg-gray-100 cursor-not-allowed' : ''}" ${isPendingCompletion ? 'disabled' : ''}>
|
||||
${getDepartmentOptions().map(opt =>
|
||||
`<option value="${opt.value}" ${opt.value === (issue.responsible_department || '') ? 'selected' : ''}>${opt.text}</option>`
|
||||
).join('')}
|
||||
@@ -812,7 +876,7 @@
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||||
<i class="fas fa-user text-purple-500 mr-1"></i>담당자
|
||||
</label>
|
||||
<input type="text" id="responsible_person_${issue.id}" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" placeholder="담당자 이름" value="${issue.responsible_person || ''}">
|
||||
<input type="text" id="responsible_person_${issue.id}" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${isPendingCompletion ? 'bg-gray-100 cursor-not-allowed' : ''}" placeholder="담당자 이름" value="${issue.responsible_person || ''}" ${isPendingCompletion ? 'readonly' : ''}>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -820,16 +884,43 @@
|
||||
<label class="block text-sm font-medium text-gray-700 mb-2">
|
||||
<i class="fas fa-calendar-alt text-red-500 mr-1"></i>조치 예상일
|
||||
</label>
|
||||
<input type="date" id="expected_completion_date_${issue.id}" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500" value="${issue.expected_completion_date ? issue.expected_completion_date.split('T')[0] : ''}">
|
||||
<input type="date" id="expected_completion_date_${issue.id}" class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-blue-500 ${isPendingCompletion ? 'bg-gray-100 cursor-not-allowed' : ''}" value="${issue.expected_completion_date ? issue.expected_completion_date.split('T')[0] : ''}" ${isPendingCompletion ? 'readonly' : ''}>
|
||||
</div>
|
||||
|
||||
<!-- 완료 대기 상태일 때 완료 정보 표시 -->
|
||||
${isPendingCompletion ? `
|
||||
<div class="mt-4 p-4 bg-purple-50 rounded-lg border border-purple-200">
|
||||
<h4 class="text-sm font-semibold text-purple-800 mb-3 flex items-center">
|
||||
<i class="fas fa-check-circle mr-2"></i>완료 신청 정보
|
||||
</h4>
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<label class="text-xs text-purple-600 font-medium">완료 사진</label>
|
||||
${issue.completion_photo_path ? `
|
||||
<div class="mt-1">
|
||||
<img src="${issue.completion_photo_path}" class="w-24 h-24 object-cover rounded-lg cursor-pointer border-2 border-purple-200 hover:border-purple-400 transition-colors" onclick="openPhotoModal('${issue.completion_photo_path}')" alt="완료 사진">
|
||||
</div>
|
||||
` : '<p class="text-xs text-gray-500 mt-1">완료 사진 없음</p>'}
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-purple-600 font-medium">완료 코멘트</label>
|
||||
<p class="text-sm text-gray-700 mt-1 p-2 bg-white rounded border">${issue.completion_comment || '코멘트 없음'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<label class="text-xs text-purple-600 font-medium">신청일시</label>
|
||||
<p class="text-sm text-gray-700 mt-1">${new Date(issue.completion_requested_at).toLocaleString('ko-KR')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
|
||||
<!-- 진행 상태 표시 -->
|
||||
<div class="mt-4 p-3 bg-blue-50 rounded-lg">
|
||||
<div class="mt-4 p-3 ${isPendingCompletion ? 'bg-purple-50' : 'bg-blue-50'} rounded-lg">
|
||||
<div class="flex items-center justify-between">
|
||||
<span class="text-sm text-blue-700 font-medium">
|
||||
<i class="fas fa-clock mr-1"></i>진행 중
|
||||
<span class="text-sm ${isPendingCompletion ? 'text-purple-700' : 'text-blue-700'} font-medium">
|
||||
<i class="${statusConfig.icon} mr-1"></i>${statusConfig.text}
|
||||
</span>
|
||||
<span class="text-xs text-blue-600">
|
||||
<span class="text-xs ${isPendingCompletion ? 'text-purple-600' : 'text-blue-600'}">
|
||||
신고일: ${new Date(issue.report_date).toLocaleDateString('ko-KR')}
|
||||
</span>
|
||||
</div>
|
||||
@@ -1638,6 +1729,216 @@
|
||||
alert('저장 중 오류가 발생했습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
// 완료 대기 상태 관련 함수들
|
||||
function editIssue(issueId) {
|
||||
// 수정 모드로 전환 (완료 대기 상태를 해제)
|
||||
if (confirm('완료 대기 상태를 해제하고 수정 모드로 전환하시겠습니까?')) {
|
||||
// 완료 신청 정보 초기화 API 호출
|
||||
resetCompletionRequest(issueId);
|
||||
}
|
||||
}
|
||||
|
||||
function rejectCompletion(issueId) {
|
||||
const reason = prompt('반려 사유를 입력하세요:');
|
||||
if (reason && reason.trim()) {
|
||||
// 반려 처리 API 호출
|
||||
rejectCompletionRequest(issueId, reason.trim());
|
||||
}
|
||||
}
|
||||
|
||||
function confirmCompletion(issueId) {
|
||||
// 모든 정보 확인 모달 열기
|
||||
openCompletionConfirmModal(issueId);
|
||||
}
|
||||
|
||||
// 완료 신청 초기화 (수정 모드로 전환)
|
||||
async function resetCompletionRequest(issueId) {
|
||||
try {
|
||||
const response = await fetch(`/api/issues/${issueId}/reset-completion`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('완료 대기 상태가 해제되었습니다. 수정이 가능합니다.');
|
||||
loadManagementData(); // 페이지 새로고침
|
||||
} else {
|
||||
const error = await response.json();
|
||||
alert(`상태 변경 실패: ${error.detail || '알 수 없는 오류'}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('상태 변경 오류:', error);
|
||||
alert('상태 변경 중 오류가 발생했습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
// 완료 신청 반려
|
||||
async function rejectCompletionRequest(issueId, reason) {
|
||||
try {
|
||||
const response = await fetch(`/api/issues/${issueId}/reject-completion`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
rejection_reason: reason
|
||||
})
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('완료 신청이 반려되었습니다.');
|
||||
loadManagementData(); // 페이지 새로고침
|
||||
} else {
|
||||
const error = await response.json();
|
||||
alert(`반려 처리 실패: ${error.detail || '알 수 없는 오류'}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('반려 처리 오류:', error);
|
||||
alert('반려 처리 중 오류가 발생했습니다.');
|
||||
}
|
||||
}
|
||||
|
||||
// 완료 확인 모달 열기
|
||||
function openCompletionConfirmModal(issueId) {
|
||||
const issue = issues.find(i => i.id === issueId);
|
||||
if (!issue) return;
|
||||
|
||||
const project = projects.find(p => p.id === issue.project_id);
|
||||
|
||||
// 모달 내용 생성
|
||||
const modalContent = `
|
||||
<div class="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center" id="completionConfirmModal">
|
||||
<div class="bg-white rounded-xl shadow-xl max-w-4xl w-full mx-4 max-h-[90vh] overflow-y-auto">
|
||||
<div class="p-6">
|
||||
<!-- 모달 헤더 -->
|
||||
<div class="flex items-center justify-between mb-6">
|
||||
<h3 class="text-xl font-semibold text-gray-900">
|
||||
<i class="fas fa-check-circle text-green-500 mr-2"></i>
|
||||
완료 확인 - No.${issue.project_sequence_no || '-'}
|
||||
</h3>
|
||||
<button onclick="closeCompletionConfirmModal()" class="text-gray-400 hover:text-gray-600 transition-colors">
|
||||
<i class="fas fa-times text-xl"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 이슈 정보 -->
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-6">
|
||||
<!-- 기본 정보 -->
|
||||
<div class="space-y-4">
|
||||
<div class="bg-blue-50 p-4 rounded-lg">
|
||||
<h4 class="font-semibold text-blue-800 mb-2">기본 정보</h4>
|
||||
<div class="space-y-2 text-sm">
|
||||
<div><span class="font-medium">프로젝트:</span> ${project ? project.project_name : '-'}</div>
|
||||
<div><span class="font-medium">부적합명:</span> ${getIssueTitle(issue)}</div>
|
||||
<div><span class="font-medium">상세내용:</span> ${getIssueDetail(issue)}</div>
|
||||
<div><span class="font-medium">원인분류:</span> ${getCategoryText(issue.final_category || issue.category)}</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-green-50 p-4 rounded-lg">
|
||||
<h4 class="font-semibold text-green-800 mb-2">관리 정보</h4>
|
||||
<div class="space-y-2 text-sm">
|
||||
<div><span class="font-medium">해결방안:</span> ${issue.solution || '-'}</div>
|
||||
<div><span class="font-medium">담당부서:</span> ${issue.responsible_department || '-'}</div>
|
||||
<div><span class="font-medium">담당자:</span> ${issue.responsible_person || '-'}</div>
|
||||
<div><span class="font-medium">조치예상일:</span> ${issue.expected_completion_date ? new Date(issue.expected_completion_date).toLocaleDateString('ko-KR') : '-'}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 완료 정보 -->
|
||||
<div class="space-y-4">
|
||||
<div class="bg-purple-50 p-4 rounded-lg">
|
||||
<h4 class="font-semibold text-purple-800 mb-2">완료 신청 정보</h4>
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<span class="font-medium text-sm">완료 사진:</span>
|
||||
${issue.completion_photo_path ? `
|
||||
<div class="mt-2">
|
||||
<img src="${issue.completion_photo_path}" class="w-32 h-32 object-cover rounded-lg border-2 border-purple-200 cursor-pointer" onclick="openPhotoModal('${issue.completion_photo_path}')" alt="완료 사진">
|
||||
</div>
|
||||
` : '<p class="text-sm text-gray-500 mt-1">완료 사진 없음</p>'}
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-medium text-sm">완료 코멘트:</span>
|
||||
<p class="text-sm text-gray-700 mt-1 p-2 bg-white rounded border">${issue.completion_comment || '코멘트 없음'}</p>
|
||||
</div>
|
||||
<div>
|
||||
<span class="font-medium text-sm">신청일시:</span>
|
||||
<p class="text-sm text-gray-700 mt-1">${new Date(issue.completion_requested_at).toLocaleString('ko-KR')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<h4 class="font-semibold text-gray-800 mb-2">업로드 사진</h4>
|
||||
<div class="flex gap-2">
|
||||
${issue.photo_path ? `<img src="${issue.photo_path}" class="w-20 h-20 object-cover rounded-lg cursor-pointer border-2 border-gray-200" onclick="openPhotoModal('${issue.photo_path}')" alt="업로드 사진 1">` : '<div class="w-20 h-20 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400 text-xs">사진 없음</div>'}
|
||||
${issue.photo_path2 ? `<img src="${issue.photo_path2}" class="w-20 h-20 object-cover rounded-lg cursor-pointer border-2 border-gray-200" onclick="openPhotoModal('${issue.photo_path2}')" alt="업로드 사진 2">` : '<div class="w-20 h-20 bg-gray-100 rounded-lg flex items-center justify-center text-gray-400 text-xs">사진 없음</div>'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 버튼 -->
|
||||
<div class="flex justify-end space-x-3">
|
||||
<button onclick="closeCompletionConfirmModal()" class="px-6 py-2 text-gray-700 bg-gray-100 rounded-lg hover:bg-gray-200 transition-colors">
|
||||
취소
|
||||
</button>
|
||||
<button onclick="finalConfirmCompletion(${issueId})" class="px-6 py-2 bg-green-500 text-white rounded-lg hover:bg-green-600 transition-colors">
|
||||
<i class="fas fa-check-circle mr-2"></i>최종 확인
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
// 모달을 body에 추가
|
||||
document.body.insertAdjacentHTML('beforeend', modalContent);
|
||||
}
|
||||
|
||||
// 완료 확인 모달 닫기
|
||||
function closeCompletionConfirmModal() {
|
||||
const modal = document.getElementById('completionConfirmModal');
|
||||
if (modal) {
|
||||
modal.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// 최종 완료 확인
|
||||
async function finalConfirmCompletion(issueId) {
|
||||
if (!confirm('이 부적합을 최종 완료 처리하시겠습니까?\n완료 처리 후에는 수정할 수 없습니다.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await fetch(`/api/issues/${issueId}/final-completion`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Authorization': `Bearer ${localStorage.getItem('access_token')}`,
|
||||
'Content-Type': 'application/json'
|
||||
}
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
alert('부적합이 최종 완료 처리되었습니다.');
|
||||
closeCompletionConfirmModal();
|
||||
loadManagementData(); // 페이지 새로고침
|
||||
} else {
|
||||
const error = await response.json();
|
||||
alert(`완료 처리 실패: ${error.detail || '알 수 없는 오류'}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('완료 처리 오류:', error);
|
||||
alert('완료 처리 중 오류가 발생했습니다.');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- 추가 정보 입력 모달 -->
|
||||
|
||||
Reference in New Issue
Block a user