refactor: 시스템 전반 코드 리팩토링 및 문의사항 UI 개선

This commit is contained in:
2026-03-17 17:49:17 +09:00
parent d0b33edea8
commit 840e7dab34
9 changed files with 221 additions and 478 deletions

View File

@@ -1,4 +1,9 @@
/**
* Project Master Overseas Inquiries JS
* 기능: 문의사항 로드, 필터링, 답변 관리, 아코디언 및 이미지 모달
*/
// --- 초기화 ---
async function loadInquiries() {
initStickyHeader();
@@ -14,7 +19,7 @@ async function loadInquiries() {
});
try {
const response = await fetch(`/api/inquiries?${params}`);
const response = await fetch(`${API.INQUIRIES}?${params}`);
const data = await response.json();
updateStats(data);
@@ -51,10 +56,10 @@ function renderInquiryList(data) {
<td title="${item.category}">${item.category}</td>
<td title="${item.project_nm}">${item.project_nm}</td>
<td class="content-preview" title="${item.content}">${item.content}</td>
<td class="content-preview" title="${item.reply || ''}" style="color: #1e5149; font-weight: 500;">${item.reply || '-'}</td>
<td title="${item.author}">${item.author}</td>
<td title="${item.reg_date}">${item.reg_date}</td>
<td><span class="status-badge ${getStatusClass(item.status)}">${item.status}</span></td>
<td class="content-preview" title="${item.reply || ''}" style="color: #1e5149; font-weight: 500;">${item.reply || '-'}</td>
<td><span class="status-badge ${Utils.getStatusClass(item.status)}">${item.status}</span></td>
</tr>
<tr id="detail-${item.id}" class="detail-row">
<td colspan="11">
@@ -129,7 +134,6 @@ function renderInquiryList(data) {
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();
@@ -137,61 +141,40 @@ function enableEdit(id) {
async function cancelEdit(id) {
try {
const response = await fetch(`/api/inquiries/${id}`);
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();
}
document.getElementById(`reply-form-${id}`).classList.replace('editable', 'readonly');
} catch { 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`, {
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("저장 중 오류가 발생했습니다.");
}
if ((await response.json()).success) { alert("저장되었습니다."); loadInquiries(); }
} catch { 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("삭제 중 오류가 발생했습니다.");
}
const response = await fetch(`${API.INQUIRIES}/${id}/reply`, { method: 'DELETE' });
if ((await response.json()).success) { alert("삭제되었습니다."); loadInquiries(); }
} catch { alert("삭제 중 오류가 발생했습니다."); }
}
function toggleAccordion(id) {
@@ -226,11 +209,6 @@ function scrollToRow(row) {
}, 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,
@@ -247,16 +225,8 @@ function updateStats(data) {
}
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';
document.getElementById('modalImage').src = src;
ModalManager.open('imageModal');
}
function toggleImageSection(id) {
@@ -268,11 +238,5 @@ function toggleImageSection(id) {
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();
});