feat: 작업 관리 페이지에 공정 관리 기능 추가
## 추가 기능 - 공정 추가/수정/삭제 기능 구현 - 공정 관리 모달 UI 추가 - 공정 탭에 편집 버튼 추가 (✏️) ## UI 변경 - 상단에 "공정 추가" 버튼 추가 - 공정 모달: 공정명, 카테고리, 설명 입력 필드 - 각 공정 탭에 편집 아이콘 표시 ## JavaScript 함수 - openWorkTypeModal(): 공정 추가 모달 열기 - editWorkType(workTypeId): 공정 수정 모달 열기 - saveWorkType(): 공정 저장 (POST/PUT) - deleteWorkType(): 공정 삭제 (연결된 작업 확인) - closeWorkTypeModal(): 모달 닫기 ## 검증 로직 - 연결된 작업이 있는 공정은 삭제 불가 - 필수 필드(공정명) 검증 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -103,9 +103,15 @@ function renderWorkTypeTabs() {
|
||||
tabsHtml += `
|
||||
<button class="tab-btn ${isActive ? 'active' : ''}"
|
||||
data-work-type="${workType.id}"
|
||||
onclick="switchWorkType(${workType.id})">
|
||||
onclick="switchWorkType(${workType.id})"
|
||||
style="position: relative; padding-right: 3rem;">
|
||||
<span class="tab-icon">🔧</span>
|
||||
${workType.name} (${count})
|
||||
<span onclick="event.stopPropagation(); editWorkType(${workType.id});"
|
||||
style="position: absolute; right: 0.5rem; padding: 0.25rem 0.5rem; opacity: 0.7; cursor: pointer; font-size: 0.75rem;"
|
||||
title="공정 수정">
|
||||
✏️
|
||||
</span>
|
||||
</button>
|
||||
`;
|
||||
});
|
||||
@@ -375,3 +381,126 @@ function showToast(message, type = 'info') {
|
||||
setTimeout(() => toast.remove(), 300);
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
// ==================== 공정 관리 ====================
|
||||
|
||||
let currentEditingWorkType = null;
|
||||
|
||||
// 공정 모달 열기 (신규)
|
||||
function openWorkTypeModal() {
|
||||
currentEditingWorkType = null;
|
||||
document.getElementById('workTypeModalTitle').textContent = '공정 추가';
|
||||
document.getElementById('workTypeId').value = '';
|
||||
document.getElementById('workTypeName').value = '';
|
||||
document.getElementById('workTypeCategory').value = '';
|
||||
document.getElementById('workTypeDescription').value = '';
|
||||
document.getElementById('deleteWorkTypeBtn').style.display = 'none';
|
||||
|
||||
document.getElementById('workTypeModal').style.display = 'flex';
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
window.openWorkTypeModal = openWorkTypeModal;
|
||||
|
||||
// 공정 수정 모달 열기
|
||||
async function editWorkType(workTypeId) {
|
||||
try {
|
||||
const workType = workTypes.find(wt => wt.id === workTypeId);
|
||||
if (!workType) {
|
||||
showToast('공정 정보를 찾을 수 없습니다.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
currentEditingWorkType = workType;
|
||||
document.getElementById('workTypeModalTitle').textContent = '공정 수정';
|
||||
document.getElementById('workTypeId').value = workType.id;
|
||||
document.getElementById('workTypeName').value = workType.name || '';
|
||||
document.getElementById('workTypeCategory').value = workType.category || '';
|
||||
document.getElementById('workTypeDescription').value = workType.description || '';
|
||||
document.getElementById('deleteWorkTypeBtn').style.display = 'block';
|
||||
|
||||
document.getElementById('workTypeModal').style.display = 'flex';
|
||||
document.body.style.overflow = 'hidden';
|
||||
} catch (error) {
|
||||
console.error('❌ 공정 조회 오류:', error);
|
||||
showToast('공정 정보를 불러올 수 없습니다.', 'error');
|
||||
}
|
||||
}
|
||||
window.editWorkType = editWorkType;
|
||||
|
||||
// 공정 모달 닫기
|
||||
function closeWorkTypeModal() {
|
||||
document.getElementById('workTypeModal').style.display = 'none';
|
||||
document.body.style.overflow = 'auto';
|
||||
currentEditingWorkType = null;
|
||||
}
|
||||
window.closeWorkTypeModal = closeWorkTypeModal;
|
||||
|
||||
// 공정 저장
|
||||
async function saveWorkType() {
|
||||
const workTypeId = document.getElementById('workTypeId').value;
|
||||
const workTypeData = {
|
||||
name: document.getElementById('workTypeName').value.trim(),
|
||||
category: document.getElementById('workTypeCategory').value.trim() || null,
|
||||
description: document.getElementById('workTypeDescription').value.trim() || null
|
||||
};
|
||||
|
||||
if (!workTypeData.name) {
|
||||
showToast('공정명을 입력해주세요.', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
let response;
|
||||
if (workTypeId) {
|
||||
// 수정
|
||||
response = await window.apiCall(`/daily-work-reports/work-types/${workTypeId}`, 'PUT', workTypeData);
|
||||
} else {
|
||||
// 신규
|
||||
response = await window.apiCall('/daily-work-reports/work-types', 'POST', workTypeData);
|
||||
}
|
||||
|
||||
if (response && response.success) {
|
||||
showToast(workTypeId ? '공정이 수정되었습니다.' : '공정이 추가되었습니다.', 'success');
|
||||
closeWorkTypeModal();
|
||||
await loadAllData();
|
||||
} else {
|
||||
throw new Error(response.message || '저장에 실패했습니다.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 공정 저장 오류:', error);
|
||||
showToast('공정 저장 중 오류가 발생했습니다.', 'error');
|
||||
}
|
||||
}
|
||||
window.saveWorkType = saveWorkType;
|
||||
|
||||
// 공정 삭제
|
||||
async function deleteWorkType() {
|
||||
if (!currentEditingWorkType) return;
|
||||
|
||||
// 이 공정에 속한 작업이 있는지 확인
|
||||
const relatedTasks = tasks.filter(t => t.work_type_id === currentEditingWorkType.id);
|
||||
if (relatedTasks.length > 0) {
|
||||
showToast(`이 공정에 ${relatedTasks.length}개의 작업이 연결되어 있어 삭제할 수 없습니다.`, 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm(`"${currentEditingWorkType.name}" 공정을 삭제하시겠습니까?`)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const response = await window.apiCall(`/daily-work-reports/work-types/${currentEditingWorkType.id}`, 'DELETE');
|
||||
|
||||
if (response && response.success) {
|
||||
showToast('공정이 삭제되었습니다.', 'success');
|
||||
closeWorkTypeModal();
|
||||
await loadAllData();
|
||||
} else {
|
||||
throw new Error(response.message || '삭제에 실패했습니다.');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ 공정 삭제 오류:', error);
|
||||
showToast('공정 삭제 중 오류가 발생했습니다.', 'error');
|
||||
}
|
||||
}
|
||||
window.deleteWorkType = deleteWorkType;
|
||||
|
||||
Reference in New Issue
Block a user