/* tkpurchase-schedule.js - Schedule management */ let schedulePage = 1; const scheduleLimit = 20; let companySearchTimer = null; async function loadSchedules() { const company = document.getElementById('filterCompany').value.trim(); const dateFrom = document.getElementById('filterDateFrom').value; const dateTo = document.getElementById('filterDateTo').value; const status = document.getElementById('filterStatus').value; let query = `?page=${schedulePage}&limit=${scheduleLimit}`; if (company) query += '&company=' + encodeURIComponent(company); if (dateFrom) query += '&date_from=' + dateFrom; if (dateTo) query += '&date_to=' + dateTo; if (status) query += '&status=' + status; try { const r = await api('/schedules' + query); renderScheduleTable(r.data || [], r.total || 0); } catch(e) { console.warn('Schedule load error:', e); document.getElementById('scheduleTableBody').innerHTML = '로딩 실패'; } } function renderScheduleTable(list, total) { const tbody = document.getElementById('scheduleTableBody'); if (!list.length) { tbody.innerHTML = '일정이 없습니다'; document.getElementById('schedulePagination').innerHTML = ''; return; } const statusMap = { scheduled: ['badge-amber', '예정'], in_progress: ['badge-green', '진행중'], completed: ['badge-blue', '완료'], cancelled: ['badge-gray', '취소'] }; tbody.innerHTML = list.map(s => { const [cls, label] = statusMap[s.status] || ['badge-gray', s.status]; const canEdit = s.status === 'scheduled'; return ` ${escapeHtml(s.company_name || '')} ${formatDate(s.work_date)} ${escapeHtml(s.work_description || '')} ${escapeHtml(s.workplace_name || '')} ${s.expected_workers || 0}명 ${label} ${canEdit ? ` ` : ''} `; }).join(''); // Pagination const totalPages = Math.ceil(total / scheduleLimit); renderSchedulePagination(totalPages); } function renderSchedulePagination(totalPages) { const container = document.getElementById('schedulePagination'); if (totalPages <= 1) { container.innerHTML = ''; return; } let html = ''; if (schedulePage > 1) { html += ``; } for (let i = 1; i <= totalPages; i++) { if (i === schedulePage) { html += ``; } else if (Math.abs(i - schedulePage) <= 2 || i === 1 || i === totalPages) { html += ``; } else if (Math.abs(i - schedulePage) === 3) { html += '...'; } } if (schedulePage < totalPages) { html += ``; } container.innerHTML = html; } function goToSchedulePage(p) { schedulePage = p; loadSchedules(); } /* ===== Company Autocomplete ===== */ function setupCompanyAutocomplete(inputId, dropdownId, hiddenId) { const input = document.getElementById(inputId); const dropdown = document.getElementById(dropdownId); const hidden = document.getElementById(hiddenId); input.addEventListener('input', function() { hidden.value = ''; clearTimeout(companySearchTimer); const q = this.value.trim(); if (q.length < 1) { dropdown.classList.add('hidden'); return; } companySearchTimer = setTimeout(async () => { try { const r = await api('/partners/search?q=' + encodeURIComponent(q)); const list = r.data || []; if (!list.length) { dropdown.innerHTML = '
결과 없음
'; } else { dropdown.innerHTML = list.map(c => `
${escapeHtml(c.company_name)}
` ).join(''); } dropdown.classList.remove('hidden'); } catch(e) { dropdown.classList.add('hidden'); } }, 300); }); input.addEventListener('blur', function() { setTimeout(() => dropdown.classList.add('hidden'), 200); }); } function selectCompany(inputId, hiddenId, dropdownId, id, name) { document.getElementById(inputId).value = name; document.getElementById(hiddenId).value = id; document.getElementById(dropdownId).classList.add('hidden'); } /* ===== Add Schedule ===== */ function openAddSchedule() { document.getElementById('addScheduleForm').reset(); document.getElementById('addCompanyId').value = ''; const tomorrow = new Date(); tomorrow.setDate(tomorrow.getDate() + 1); document.getElementById('addWorkDate').value = tomorrow.toISOString().substring(0, 10); document.getElementById('addScheduleModal').classList.remove('hidden'); } function closeAddSchedule() { document.getElementById('addScheduleModal').classList.add('hidden'); } async function submitAddSchedule(e) { e.preventDefault(); const companyId = document.getElementById('addCompanyId').value; if (!companyId) { showToast('업체를 선택하세요', 'error'); return; } const body = { partner_company_id: parseInt(companyId), work_date: document.getElementById('addWorkDate').value, work_description: document.getElementById('addWorkDescription').value.trim(), workplace_name: document.getElementById('addWorkplaceName').value.trim(), expected_workers: parseInt(document.getElementById('addExpectedWorkers').value) || 0, notes: document.getElementById('addNotes').value.trim() }; try { await api('/schedules', { method: 'POST', body: JSON.stringify(body) }); showToast('일정이 등록되었습니다'); closeAddSchedule(); loadSchedules(); } catch(e) { showToast(e.message || '등록 실패', 'error'); } } /* ===== Edit Schedule ===== */ let scheduleCache = {}; async function openEditSchedule(id) { try { const r = await api('/schedules/' + id); const s = r.data || r; scheduleCache[id] = s; document.getElementById('editScheduleId').value = id; document.getElementById('editCompanySearch').value = s.company_name || ''; document.getElementById('editCompanyId').value = s.partner_company_id || ''; document.getElementById('editWorkDate').value = formatDate(s.work_date); document.getElementById('editWorkDescription').value = s.work_description || ''; document.getElementById('editWorkplaceName').value = s.workplace_name || ''; document.getElementById('editExpectedWorkers').value = s.expected_workers || 0; document.getElementById('editNotes').value = s.notes || ''; document.getElementById('editScheduleModal').classList.remove('hidden'); } catch(e) { showToast('일정 정보를 불러올 수 없습니다', 'error'); } } function closeEditSchedule() { document.getElementById('editScheduleModal').classList.add('hidden'); } async function submitEditSchedule(e) { e.preventDefault(); const id = document.getElementById('editScheduleId').value; const companyId = document.getElementById('editCompanyId').value; if (!companyId) { showToast('업체를 선택하세요', 'error'); return; } const body = { partner_company_id: parseInt(companyId), work_date: document.getElementById('editWorkDate').value, work_description: document.getElementById('editWorkDescription').value.trim(), workplace_name: document.getElementById('editWorkplaceName').value.trim(), expected_workers: parseInt(document.getElementById('editExpectedWorkers').value) || 0, notes: document.getElementById('editNotes').value.trim() }; try { await api('/schedules/' + id, { method: 'PUT', body: JSON.stringify(body) }); showToast('일정이 수정되었습니다'); closeEditSchedule(); loadSchedules(); } catch(e) { showToast(e.message || '수정 실패', 'error'); } } /* ===== Delete Schedule ===== */ async function deleteSchedule(id) { if (!confirm('이 일정을 삭제하시겠습니까?')) return; try { await api('/schedules/' + id, { method: 'DELETE' }); showToast('일정이 삭제되었습니다'); loadSchedules(); } catch(e) { showToast(e.message || '삭제 실패', 'error'); } } /* ===== Init ===== */ function initSchedulePage() { if (!initAuth()) return; // Set default date range const now = new Date(); const firstDay = new Date(now.getFullYear(), now.getMonth(), 1); const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0); document.getElementById('filterDateFrom').value = firstDay.toISOString().substring(0, 10); document.getElementById('filterDateTo').value = lastDay.toISOString().substring(0, 10); // Setup autocomplete for both modals setupCompanyAutocomplete('addCompanySearch', 'addCompanyDropdown', 'addCompanyId'); setupCompanyAutocomplete('editCompanySearch', 'editCompanyDropdown', 'editCompanyId'); loadSchedules(); }