/* ===== Checklist Management (체크리스트 관리 - 관리자) ===== */
let checklistItems = [];
let weatherConditions = [];
let workTypes = [];
let editingItemId = null;
let currentTab = 'basic';
/* ===== Tab switching ===== */
function switchTab(tab) {
currentTab = tab;
['basic', 'weather', 'worktype'].forEach(t => {
document.getElementById('panel' + t.charAt(0).toUpperCase() + t.slice(1)).classList.toggle('hidden', t !== tab);
const tabBtn = document.getElementById('tab' + t.charAt(0).toUpperCase() + t.slice(1));
if (t === tab) {
tabBtn.classList.add('active');
} else {
tabBtn.classList.remove('active');
}
});
}
/* ===== Load checklist items ===== */
async function loadChecklistItems() {
try {
const res = await api('/checklist');
checklistItems = res.data || [];
renderBasicItems();
renderWeatherItems();
renderWorktypeItems();
} catch (e) {
showToast('체크리스트 로드 실패: ' + e.message, 'error');
}
}
/* ===== Load lookup data ===== */
async function loadLookupData() {
try {
const [wcRes, wtRes] = await Promise.all([
api('/checklist/weather-conditions'),
api('/checklist/work-types')
]);
weatherConditions = wcRes.data || [];
workTypes = wtRes.data || [];
// Populate selects
document.getElementById('itemWeatherCondition').innerHTML = '' +
weatherConditions.map(w => ``).join('');
document.getElementById('itemWorkType').innerHTML = '' +
workTypes.map(w => ``).join('');
} catch (e) {
console.error('Lookup data load error:', e);
}
}
/* ===== Load tasks by work type ===== */
async function loadTasksByWorkType(workTypeId) {
const taskSelect = document.getElementById('itemTask');
if (!workTypeId) {
taskSelect.innerHTML = '';
document.getElementById('taskField').classList.add('hidden');
return;
}
try {
const res = await api('/checklist/tasks/' + workTypeId);
const tasks = res.data || [];
taskSelect.innerHTML = '' +
tasks.map(t => ``).join('');
document.getElementById('taskField').classList.remove('hidden');
} catch (e) {
console.error('Task load error:', e);
taskSelect.innerHTML = '';
}
}
/* ===== Work type change handler ===== */
function onWorkTypeChange() {
const workTypeId = document.getElementById('itemWorkType').value;
loadTasksByWorkType(workTypeId);
}
/* ===== Render basic items ===== */
function renderBasicItems() {
const items = checklistItems.filter(i => i.item_type === 'basic');
const container = document.getElementById('basicItemsList');
if (!items.length) {
container.innerHTML = '
기본 항목이 없습니다
';
return;
}
// Group by category
const groups = {};
items.forEach(i => {
const cat = i.category || '미분류';
if (!groups[cat]) groups[cat] = [];
groups[cat].push(i);
});
container.innerHTML = Object.entries(groups).map(([cat, items]) => `
${escapeHtml(cat)}
${items.map(i => renderItemRow(i)).join('')}
`).join('');
}
/* ===== Render weather items ===== */
function renderWeatherItems() {
const items = checklistItems.filter(i => i.item_type === 'weather');
const container = document.getElementById('weatherItemsList');
if (!items.length) {
container.innerHTML = '날씨별 항목이 없습니다
';
return;
}
// Group by weather condition
const groups = {};
items.forEach(i => {
const cond = i.weather_condition_name || '미지정';
if (!groups[cond]) groups[cond] = [];
groups[cond].push(i);
});
container.innerHTML = Object.entries(groups).map(([cond, items]) => `
${escapeHtml(cond)}
${items.map(i => renderItemRow(i)).join('')}
`).join('');
}
/* ===== Render worktype items (2-level: work_type → task) ===== */
function renderWorktypeItems() {
const items = checklistItems.filter(i => i.item_type === 'task');
const container = document.getElementById('worktypeItemsList');
if (!items.length) {
container.innerHTML = '작업별 항목이 없습니다
';
return;
}
// 2-level grouping: work_type → task
const wtGroups = {};
items.forEach(i => {
const wt = i.work_type_name || '미지정';
if (!wtGroups[wt]) wtGroups[wt] = {};
const task = i.task_name || '미지정';
if (!wtGroups[wt][task]) wtGroups[wt][task] = [];
wtGroups[wt][task].push(i);
});
container.innerHTML = Object.entries(wtGroups).map(([wt, taskGroups]) => `
${escapeHtml(wt)}
${Object.entries(taskGroups).map(([task, items]) => `
${escapeHtml(task)}
${items.map(i => renderItemRow(i)).join('')}
`).join('')}
`).join('');
}
/* ===== Render single item row ===== */
function renderItemRow(item) {
const activeClass = item.is_active ? '' : 'opacity-50';
const activeIcon = item.is_active
? ''
: '';
return `
${activeIcon}
${escapeHtml(item.item_content)}
${item.category ? `${escapeHtml(item.category)}` : ''}
#${item.display_order}
`;
}
/* ===== Add/Edit Modal ===== */
function openAddItem(tab) {
editingItemId = null;
document.getElementById('itemModalTitle').textContent = '체크리스트 항목 추가';
document.getElementById('itemForm').reset();
document.getElementById('itemIsActive').checked = true;
document.getElementById('itemDisplayOrder').value = '0';
// Set type based on tab
const typeMap = { basic: 'basic', weather: 'weather', worktype: 'task' };
document.getElementById('itemType').value = typeMap[tab] || 'basic';
toggleTypeFields();
document.getElementById('itemModal').classList.remove('hidden');
}
async function openEditItem(id) {
const item = checklistItems.find(i => i.item_id === id);
if (!item) return;
editingItemId = id;
document.getElementById('itemModalTitle').textContent = '체크리스트 항목 수정';
document.getElementById('itemType').value = item.item_type;
document.getElementById('itemCategory').value = item.category || '';
document.getElementById('itemContent').value = item.item_content || '';
document.getElementById('itemDisplayOrder').value = item.display_order || 0;
document.getElementById('itemIsActive').checked = item.is_active !== false && item.is_active !== 0;
if (item.weather_condition_id) {
document.getElementById('itemWeatherCondition').value = item.weather_condition_id;
}
if (item.work_type_id) {
document.getElementById('itemWorkType').value = item.work_type_id;
// Load tasks first, then set value after load completes
await loadTasksByWorkType(item.work_type_id);
if (item.task_id) {
document.getElementById('itemTask').value = item.task_id;
}
}
toggleTypeFields();
document.getElementById('itemModal').classList.remove('hidden');
}
function closeItemModal() {
document.getElementById('itemModal').classList.add('hidden');
document.getElementById('taskField').classList.add('hidden');
editingItemId = null;
}
function toggleTypeFields() {
const type = document.getElementById('itemType').value;
document.getElementById('weatherConditionField').classList.toggle('hidden', type !== 'weather');
document.getElementById('workTypeField').classList.toggle('hidden', type !== 'task');
// Hide task field when type changes away from task
if (type !== 'task') {
document.getElementById('taskField').classList.add('hidden');
} else {
// Show task field if work type is already selected
const workTypeId = document.getElementById('itemWorkType').value;
if (workTypeId) {
document.getElementById('taskField').classList.remove('hidden');
}
}
}
/* ===== Submit item ===== */
async function submitItem(e) {
e.preventDefault();
const data = {
item_type: document.getElementById('itemType').value,
category: document.getElementById('itemCategory').value.trim() || null,
item_content: document.getElementById('itemContent').value.trim(),
display_order: parseInt(document.getElementById('itemDisplayOrder').value) || 0,
is_active: document.getElementById('itemIsActive').checked
};
if (!data.item_content) { showToast('점검 항목을 입력해주세요', 'error'); return; }
if (data.item_type === 'weather') {
data.weather_condition_id = parseInt(document.getElementById('itemWeatherCondition').value) || null;
if (!data.weather_condition_id) { showToast('날씨 조건을 선택해주세요', 'error'); return; }
}
if (data.item_type === 'task') {
const taskId = parseInt(document.getElementById('itemTask').value) || null;
if (!taskId) { showToast('작업을 선택해주세요', 'error'); return; }
data.task_id = taskId;
}
try {
if (editingItemId) {
await api('/checklist/' + editingItemId, { method: 'PUT', body: JSON.stringify(data) });
showToast('수정되었습니다');
} else {
await api('/checklist', { method: 'POST', body: JSON.stringify(data) });
showToast('추가되었습니다');
}
closeItemModal();
await loadChecklistItems();
} catch (e) {
showToast(e.message, 'error');
}
}
/* ===== Delete item ===== */
async function doDeleteItem(id) {
if (!confirm('이 항목을 삭제하시겠습니까?')) return;
try {
await api('/checklist/' + id, { method: 'DELETE' });
showToast('삭제되었습니다');
await loadChecklistItems();
} catch (e) {
showToast(e.message, 'error');
}
}
/* ===== Init ===== */
function initChecklistPage() {
if (!initAuth()) return;
// Check admin
const isAdmin = currentUser && ['admin', 'system'].includes(currentUser.role);
if (!isAdmin) {
document.querySelector('.flex-1.min-w-0').innerHTML = `
`;
return;
}
// Type change handler
document.getElementById('itemType').addEventListener('change', toggleTypeFields);
document.getElementById('itemWorkType').addEventListener('change', onWorkTypeChange);
document.getElementById('itemForm').addEventListener('submit', submitItem);
loadLookupData();
loadChecklistItems();
}