async function loadInquiries() { initStickyHeader(); const pmType = document.getElementById('filterPmType').value; const category = document.getElementById('filterCategory').value; const status = document.getElementById('filterStatus').value; const keyword = document.getElementById('searchKeyword').value; const params = new URLSearchParams({ pm_type: pmType, category: category, keyword: keyword }); try { const response = await fetch(`/api/inquiries?${params}`); const data = await response.json(); updateStats(data); const filteredData = status ? data.filter(item => item.status === status) : data; renderInquiryList(filteredData); } catch (e) { console.error("데이터 로딩 중 오류 발생:", e); } } function initStickyHeader() { const header = document.getElementById('stickyHeader'); const thead = document.querySelector('.inquiry-table thead'); if (header && thead) { const headerHeight = header.offsetHeight; const totalOffset = 36 + headerHeight; document.querySelectorAll('.inquiry-table thead th').forEach(th => { th.style.top = totalOffset + 'px'; }); } } function renderInquiryList(data) { const tbody = document.getElementById('inquiryList'); tbody.innerHTML = data.map(item => ` ${item.no} ${item.image_url ? `thumbnail` : '없음'} ${item.pm_type} ${item.browser || 'Chrome'} ${item.category} ${item.project_nm} ${item.content} ${item.reply || '-'} ${item.author} ${item.reg_date} ${item.status}
작성자: ${item.author}
등록일: ${item.reg_date}
시스템: ${item.pm_type}
환경: ${item.browser || 'Chrome'} / ${item.device || 'PC'}

[질문 내용]

${item.content}
${item.image_url ? `

🖼️ [첨부 이미지] (클릭 시 크게 보기)

` : ''}

[조치 및 답변]

${item.handled_date ? `
최종 수정일: ${item.handled_date}
` : ''}
`).join(''); } function enableEdit(id) { const form = document.getElementById(`reply-form-${id}`); form.classList.replace('readonly', 'editable'); const elements = [`reply-text-${id}`, `reply-status-${id}`, `reply-handler-${id}`]; elements.forEach(elId => document.getElementById(elId).disabled = false); document.getElementById(`reply-text-${id}`).focus(); } async function cancelEdit(id) { try { const response = await fetch(`/api/inquiries/${id}`); const item = await response.json(); const form = document.getElementById(`reply-form-${id}`); const txt = document.getElementById(`reply-text-${id}`); const status = document.getElementById(`reply-status-${id}`); const handler = document.getElementById(`reply-handler-${id}`); txt.value = item.reply || ''; status.value = item.status; handler.value = item.handler || ''; [txt, status, handler].forEach(el => el.disabled = true); form.classList.replace('editable', 'readonly'); } catch (e) { loadInquiries(); } } async function saveReply(id) { const reply = document.getElementById(`reply-text-${id}`).value; const status = document.getElementById(`reply-status-${id}`).value; const handler = document.getElementById(`reply-handler-${id}`).value; if (!reply.trim() || !handler.trim()) return alert("내용과 처리자를 모두 입력해 주세요."); try { const response = await fetch(`/api/inquiries/${id}/reply`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ reply, status, handler }) }); const result = await response.json(); if (result.success) { alert("저장되었습니다."); loadInquiries(); } } catch (e) { alert("저장 중 오류가 발생했습니다."); } } async function deleteReply(id) { if (!confirm("답변을 삭제하시겠습니까?")) return; try { const response = await fetch(`/api/inquiries/${id}/reply`, { method: 'DELETE' }); const result = await response.json(); if (result.success) { alert("삭제되었습니다."); loadInquiries(); } } catch (e) { alert("삭제 중 오류가 발생했습니다."); } } function toggleAccordion(id) { const detailRow = document.getElementById(`detail-${id}`); if (!detailRow) return; const inquiryRow = detailRow.previousElementSibling; const isActive = detailRow.classList.contains('active'); document.querySelectorAll('.detail-row.active').forEach(row => { if (row.id !== `detail-${id}`) { row.classList.remove('active'); if (row.previousElementSibling) row.previousElementSibling.classList.remove('active-row'); } }); if (isActive) { detailRow.classList.remove('active'); inquiryRow.classList.remove('active-row'); } else { detailRow.classList.add('active'); inquiryRow.classList.add('active-row'); scrollToRow(inquiryRow); } } function scrollToRow(row) { setTimeout(() => { const headerHeight = document.getElementById('stickyHeader').offsetHeight; const totalOffset = 36 + headerHeight + 40; const offsetPosition = (row.getBoundingClientRect().top + window.pageYOffset) - totalOffset; window.scrollTo({ top: offsetPosition, behavior: 'smooth' }); }, 100); } function getStatusClass(status) { const map = { '완료': 'status-complete', '작업 중': 'status-working', '확인 중': 'status-checking' }; return map[status] || 'status-pending'; } function updateStats(data) { const counts = { Total: data.length, Complete: data.filter(i => i.status === '완료').length, Working: data.filter(i => i.status === '작업 중').length, Checking: data.filter(i => i.status === '확인 중').length, Pending: data.filter(i => i.status === '개발예정').length, Unconfirmed: data.filter(i => i.status === '미확인').length }; Object.keys(counts).forEach(k => { const el = document.getElementById(`count${k}`); if (el) el.textContent = counts[k].toLocaleString(); }); } function openImageModal(src) { const modal = document.getElementById('imageModal'); if (modal) { document.getElementById('modalImage').src = src; modal.style.display = 'flex'; } } function closeImageModal() { const modal = document.getElementById('imageModal'); if (modal) modal.style.display = 'none'; } function toggleImageSection(id) { const section = document.getElementById(`img-section-${id}`); const content = document.getElementById(`img-content-${id}`); const icon = section.querySelector('.toggle-icon'); const isCollapsed = content.classList.toggle('collapsed'); section.classList.toggle('active', !isCollapsed); icon.textContent = isCollapsed ? '▼' : '▲'; } // Global Initialization document.addEventListener('DOMContentLoaded', loadInquiries); window.addEventListener('resize', initStickyHeader); // Global Key Events (ESC) document.addEventListener('keydown', (e) => { if (e.key === 'Escape') closeImageModal(); });