/* ===== Tasks CRUD ===== */
let taskWorkTypes = [], allTasks = [], tasksLoaded = false;
let selectedTaskWorkTypeFilter = null;
async function loadTasksTab() {
await loadWorkTypes();
await loadTasks();
tasksLoaded = true;
}
async function loadWorkTypes() {
try {
const r = await api('/tasks/work-types');
taskWorkTypes = r.data || [];
renderWorkTypeSidebar();
populateTaskWorkTypeSelect();
} catch(e) { console.warn('공정 로드 실패:', e); }
}
function renderWorkTypeSidebar() {
const c = document.getElementById('workTypeSidebar');
if (!c) return;
let html = `
전체
${allTasks.length}
`;
// 카테고리별 그룹핑
const grouped = {};
taskWorkTypes.forEach(wt => {
const cat = wt.category || '미분류';
if (!grouped[cat]) grouped[cat] = [];
grouped[cat].push(wt);
});
Object.keys(grouped).sort().forEach(cat => {
html += `${cat}
`;
grouped[cat].forEach(wt => {
const count = allTasks.filter(t => t.work_type_id === wt.id).length;
const isActive = selectedTaskWorkTypeFilter === wt.id;
html += ``;
});
});
// 미지정 작업 수
const noType = allTasks.filter(t => !t.work_type_id).length;
if (noType > 0) {
html += `
미지정
${noType}
`;
}
c.innerHTML = html;
}
function populateTaskWorkTypeSelect() {
const sel = document.getElementById('taskWorkType');
if (!sel) return;
const val = sel.value;
sel.innerHTML = '';
taskWorkTypes.forEach(wt => {
sel.innerHTML += ``;
});
sel.value = val;
}
function filterTasksByWorkType(wtId) {
selectedTaskWorkTypeFilter = wtId;
renderWorkTypeSidebar();
displayTasks();
}
async function loadTasks() {
try {
const r = await api('/tasks');
allTasks = r.data || [];
renderWorkTypeSidebar();
displayTasks();
} catch(e) {
document.getElementById('taskList').innerHTML = ``;
}
}
function displayTasks() {
const c = document.getElementById('taskList');
let filtered = allTasks;
let label = '전체';
if (selectedTaskWorkTypeFilter === 0) {
filtered = allTasks.filter(t => !t.work_type_id);
label = '미지정';
} else if (selectedTaskWorkTypeFilter) {
filtered = allTasks.filter(t => t.work_type_id === selectedTaskWorkTypeFilter);
const wt = taskWorkTypes.find(w => w.id === selectedTaskWorkTypeFilter);
label = wt ? wt.name : '';
}
document.getElementById('taskFilterLabel').textContent = `- ${label}`;
const active = filtered.filter(t => t.is_active).length;
const inactive = filtered.length - active;
document.getElementById('taskStats').textContent = `활성 ${active} / 비활성 ${inactive}`;
if (!filtered.length) { c.innerHTML = '등록된 작업이 없습니다.
'; return; }
c.innerHTML = filtered.map(t => `
${escHtml(t.task_name)}
${t.work_type_name ? `${escHtml(t.work_type_name)}` : '미지정'}
${t.description ? `${escHtml(t.description)}` : ''}
${t.is_active ? '활성' : '비활성'}
`).join('');
}
// 공정 모달
function openWorkTypeModal(editId) {
document.getElementById('wtEditId').value = '';
document.getElementById('workTypeForm').reset();
document.getElementById('workTypeModalTitle').textContent = '공정 추가';
if (editId) {
const wt = taskWorkTypes.find(w => w.id === editId);
if (!wt) return;
document.getElementById('workTypeModalTitle').textContent = '공정 수정';
document.getElementById('wtEditId').value = wt.id;
document.getElementById('wtName').value = wt.name || '';
document.getElementById('wtCategory').value = wt.category || '';
document.getElementById('wtDesc').value = wt.description || '';
}
document.getElementById('workTypeModal').classList.remove('hidden');
}
function closeWorkTypeModal() { document.getElementById('workTypeModal').classList.add('hidden'); }
function editWorkType(id) { openWorkTypeModal(id); }
document.getElementById('workTypeForm').addEventListener('submit', async e => {
e.preventDefault();
const editId = document.getElementById('wtEditId').value;
const body = {
name: document.getElementById('wtName').value.trim(),
category: document.getElementById('wtCategory').value.trim() || null,
description: document.getElementById('wtDesc').value.trim() || null
};
try {
if (editId) {
await api(`/tasks/work-types/${editId}`, { method: 'PUT', body: JSON.stringify(body) });
showToast('공정이 수정되었습니다.');
} else {
await api('/tasks/work-types', { method: 'POST', body: JSON.stringify(body) });
showToast('공정이 추가되었습니다.');
}
closeWorkTypeModal();
await loadWorkTypes();
await loadTasks();
} catch(e) { showToast(e.message, 'error'); }
});
// 작업 모달
function openTaskModal(editId) {
document.getElementById('taskEditId').value = '';
document.getElementById('taskForm').reset();
document.getElementById('taskActive').checked = true;
document.getElementById('taskModalTitle').textContent = '작업 추가';
populateTaskWorkTypeSelect();
// 사이드바 필터 선택된 공정 자동 선택
if (!editId && selectedTaskWorkTypeFilter && selectedTaskWorkTypeFilter !== 0) {
document.getElementById('taskWorkType').value = selectedTaskWorkTypeFilter;
}
if (editId) {
const t = allTasks.find(x => x.task_id === editId);
if (!t) return;
document.getElementById('taskModalTitle').textContent = '작업 수정';
document.getElementById('taskEditId').value = t.task_id;
document.getElementById('taskName').value = t.task_name || '';
document.getElementById('taskWorkType').value = t.work_type_id || '';
document.getElementById('taskDesc').value = t.description || '';
document.getElementById('taskActive').checked = !!t.is_active;
}
document.getElementById('taskModal').classList.remove('hidden');
}
function closeTaskModal() { document.getElementById('taskModal').classList.add('hidden'); }
function editTask(id) { openTaskModal(id); }
document.getElementById('taskForm').addEventListener('submit', async e => {
e.preventDefault();
const editId = document.getElementById('taskEditId').value;
const body = {
task_name: document.getElementById('taskName').value.trim(),
work_type_id: document.getElementById('taskWorkType').value ? parseInt(document.getElementById('taskWorkType').value) : null,
description: document.getElementById('taskDesc').value.trim() || null,
is_active: document.getElementById('taskActive').checked ? 1 : 0
};
try {
if (editId) {
await api(`/tasks/${editId}`, { method: 'PUT', body: JSON.stringify(body) });
showToast('작업이 수정되었습니다.');
} else {
await api('/tasks', { method: 'POST', body: JSON.stringify(body) });
showToast('작업이 추가되었습니다.');
}
closeTaskModal();
await loadTasks();
} catch(e) { showToast(e.message, 'error'); }
});
async function deleteTask(id, name) {
if (!confirm(`"${name}" 작업을 삭제하시겠습니까?`)) return;
try {
await api(`/tasks/${id}`, { method: 'DELETE' });
showToast('작업이 삭제되었습니다.');
await loadTasks();
} catch(e) { showToast(e.message, 'error'); }
}