// ChemiFactory MES - Supplier Management Frontend Logic const API_BASE = "/suppliers"; let allSuppliers = []; let selectedSupplierId = null; document.addEventListener("DOMContentLoaded", () => { initEvents(); fetchSuppliers(); }); // APIs Integration async function fetchSuppliers() { try { const res = await fetch(`${API_BASE}/`); if (!res.ok) throw new Error("Failed to fetch suppliers"); allSuppliers = await res.json(); renderSupplierList(allSuppliers); } catch (err) { console.error(err); showListError(); } } async function showSupplierDetail(id) { try { selectedSupplierId = id; const res = await fetch(`${API_BASE}/${id}`); if (!res.ok) throw new Error("Failed to fetch supplier details"); const data = await res.json(); renderSupplierDetail(data); } catch (err) { console.error(err); alert("공급사 정보를 상세히 불러오지 못했습니다."); } } // Render Lists function renderSupplierList(list) { const tbody = document.getElementById("supplier-list-body"); tbody.innerHTML = ""; if (list.length === 0) { tbody.innerHTML = `등록된 공급사가 없습니다.`; return; } list.forEach(supp => { const tr = document.createElement("tr"); if (selectedSupplierId === supp.id) tr.className = "active-row"; tr.innerHTML = ` ${supp.name_kr} ${supp.contact_number || "-"} ${supp.business_registration_number || "-"} `; tr.addEventListener("click", () => { document.querySelectorAll("#supplier-list-body tr").forEach(el => el.classList.remove("active-row")); tr.classList.add("active-row"); showSupplierDetail(supp.id); }); tbody.appendChild(tr); }); } function showListError() { const tbody = document.getElementById("supplier-list-body"); tbody.innerHTML = `데이터 통신에 실패했습니다. DB 작동을 확인하십시오.`; } function renderSupplierDetail(data) { // Show details card, hide placeholder document.getElementById("supplier-placeholder-card").style.display = "none"; document.getElementById("supplier-detail-card").style.display = "block"; const supp = data.supplier; document.getElementById("detail-name-kr").innerText = supp.name_kr; document.getElementById("detail-name-en").innerText = supp.name_en || ""; document.getElementById("detail-brn").innerText = supp.business_registration_number || "-"; document.getElementById("detail-contact").innerText = supp.contact_number || "-"; document.getElementById("detail-address").innerText = supp.address || "-"; // Bind Contacts renderContactsList(data.contacts || []); // Bind Purchase Activities renderActivitiesList(data.purchaseActivities || []); } function renderContactsList(contacts) { const tbody = document.getElementById("contact-list-body"); tbody.innerHTML = ""; if (contacts.length === 0) { tbody.innerHTML = `등록된 담당자가 없습니다.`; return; } contacts.forEach(c => { const tr = document.createElement("tr"); tr.innerHTML = ` ${c.name} ${c.position || "-"} ${c.work_location ? `(${c.work_location})` : ""} ${c.phone_number || "-"} ${c.email || "-"} `; tbody.appendChild(tr); }); } function renderActivitiesList(activities) { const tbody = document.getElementById("activity-list-body"); tbody.innerHTML = ""; if (activities.length === 0) { tbody.innerHTML = `매입 활동 내역이 없습니다.`; return; } // Sort by date descending activities.sort((a, b) => new Date(b.activity_date) - new Date(a.activity_date)); activities.forEach(act => { const tr = document.createElement("tr"); tr.innerHTML = ` ${act.activity_date} ${act.activity_type} ${act.memo} `; tbody.appendChild(tr); }); } // Event Bindings function initEvents() { // Search Filter document.getElementById("search-supplier").addEventListener("input", (e) => { const query = e.target.value.toLowerCase(); const filtered = allSuppliers.filter(c => c.name_kr.toLowerCase().includes(query) || (c.name_en && c.name_en.toLowerCase().includes(query)) || (c.business_registration_number && c.business_registration_number.includes(query)) ); renderSupplierList(filtered); }); // Tab Toggle document.querySelectorAll(".tab-btn").forEach(btn => { btn.addEventListener("click", () => { document.querySelectorAll(".tab-btn").forEach(b => b.classList.remove("active")); document.querySelectorAll(".tab-content").forEach(tc => tc.classList.remove("active")); btn.classList.add("active"); document.getElementById(btn.dataset.tab).classList.add("active"); }); }); // Modals Control const modals = ["supplier-modal", "contact-modal", "activity-modal"]; modals.forEach(mId => { const modal = document.getElementById(mId); modal.querySelectorAll(".close-btn, .close-modal-btn").forEach(btn => { btn.addEventListener("click", () => modal.style.display = "none"); }); }); // Add Supplier document.getElementById("btn-add-supplier").addEventListener("click", () => { document.getElementById("supplier-form").reset(); document.getElementById("supplier-id").value = ""; document.getElementById("supplier-modal-title").innerText = "공급사 등록"; document.getElementById("supplier-modal").style.display = "flex"; }); document.getElementById("supplier-form").addEventListener("submit", handleSupplierSubmit); // Edit & Delete Supplier document.getElementById("btn-edit-supplier").addEventListener("click", () => { const activeSupp = allSuppliers.find(c => c.id === selectedSupplierId); if (!activeSupp) return; document.getElementById("supplier-id").value = activeSupp.id; document.getElementById("supp-name-kr").value = activeSupp.name_kr; document.getElementById("supp-name-en").value = activeSupp.name_en || ""; document.getElementById("supp-brn").value = activeSupp.business_registration_number || ""; document.getElementById("supp-contact").value = activeSupp.contact_number || ""; document.getElementById("supp-address").value = activeSupp.address || ""; document.getElementById("supplier-modal-title").innerText = "공급사 정보 수정"; document.getElementById("supplier-modal").style.display = "flex"; }); document.getElementById("btn-delete-supplier").addEventListener("click", handleDeleteSupplier); // Add Contact document.getElementById("btn-add-contact").addEventListener("click", () => { document.getElementById("contact-form").reset(); document.getElementById("contact-id").value = ""; document.getElementById("contact-modal-title").innerText = "담당자 등록"; document.getElementById("contact-modal").style.display = "flex"; }); document.getElementById("contact-form").addEventListener("submit", handleContactSubmit); // Add Activity document.getElementById("btn-add-activity").addEventListener("click", () => { document.getElementById("activity-form").reset(); document.getElementById("activity-id").value = ""; document.getElementById("act-date").value = new Date().toISOString().substring(0, 10); document.getElementById("activity-modal-title").innerText = "매입 일지 등록"; document.getElementById("activity-modal").style.display = "flex"; }); document.getElementById("activity-form").addEventListener("submit", handleActivitySubmit); } // Form Handlers async function handleSupplierSubmit(e) { e.preventDefault(); const id = document.getElementById("supplier-id").value; const payload = { name_kr: document.getElementById("supp-name-kr").value, name_en: document.getElementById("supp-name-en").value || null, business_registration_number: document.getElementById("supp-brn").value || null, contact_number: document.getElementById("supp-contact").value || null, address: document.getElementById("supp-address").value || null }; try { let res; if (id) { // Update res = await fetch(`${API_BASE}/${id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); } else { // Create res = await fetch(`${API_BASE}/`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); } if (!res.ok) throw new Error("API error occurred"); const result = await res.json(); document.getElementById("supplier-modal").style.display = "none"; await fetchSuppliers(); if (id) { showSupplierDetail(parseInt(id)); } else { showSupplierDetail(result.id); } } catch (err) { console.error(err); alert("공급사 정보를 저장하는 중 오류가 발생했습니다."); } } async function handleDeleteSupplier() { if (!selectedSupplierId) return; if (!confirm("이 공급사를 정말 삭제하시겠습니까?\n해당 공급사의 연락처 및 매입 일지 정보가 영구 삭제됩니다.")) return; try { const res = await fetch(`${API_BASE}/${selectedSupplierId}`, { method: "DELETE" }); if (!res.ok) throw new Error("Failed to delete supplier"); selectedSupplierId = null; document.getElementById("supplier-detail-card").style.display = "none"; document.getElementById("supplier-placeholder-card").style.display = "flex"; await fetchSuppliers(); } catch (err) { console.error(err); alert("공급사 삭제에 실패했습니다."); } } // Contact Handlers window.openEditContactModal = function(contact) { document.getElementById("contact-id").value = contact.id; document.getElementById("cont-name").value = contact.name; document.getElementById("cont-position").value = contact.position || ""; document.getElementById("cont-phone").value = contact.phone_number || ""; document.getElementById("cont-email").value = contact.email || ""; document.getElementById("cont-location").value = contact.work_location || ""; document.getElementById("contact-modal-title").innerText = "담당자 정보 수정"; document.getElementById("contact-modal").style.display = "flex"; }; async function handleContactSubmit(e) { e.preventDefault(); const id = document.getElementById("contact-id").value; const payload = { supplier_id: selectedSupplierId, name: document.getElementById("cont-name").value, position: document.getElementById("cont-position").value || null, phone_number: document.getElementById("cont-phone").value || null, email: document.getElementById("cont-email").value || null, work_location: document.getElementById("cont-location").value || null }; try { let res; if (id) { res = await fetch(`${API_BASE}/contacts/${id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); } else { res = await fetch(`${API_BASE}/contacts`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); } if (!res.ok) throw new Error("Contact save API error"); document.getElementById("contact-modal").style.display = "none"; showSupplierDetail(selectedSupplierId); } catch (err) { console.error(err); alert("담당자 저장에 실패했습니다."); } } window.deleteContact = async function(contactId) { if (!confirm("이 담당자 정보를 정말 삭제하시겠습니까?")) return; try { const res = await fetch(`${API_BASE}/contacts/${contactId}`, { method: "DELETE" }); if (!res.ok) throw new Error("Failed to delete contact"); showSupplierDetail(selectedSupplierId); } catch (err) { console.error(err); alert("담당자 삭제에 실패했습니다."); } }; // Activity Handlers window.openEditActivityModal = function(act) { document.getElementById("activity-id").value = act.id; document.getElementById("act-date").value = act.activity_date; document.getElementById("act-type").value = act.activity_type; document.getElementById("act-memo").value = act.memo || ""; document.getElementById("activity-modal-title").innerText = "매입 일지 수정"; document.getElementById("activity-modal").style.display = "flex"; }; async function handleActivitySubmit(e) { e.preventDefault(); const id = document.getElementById("activity-id").value; const payload = { supplier_id: selectedSupplierId, contact_id: null, activity_date: document.getElementById("act-date").value, activity_type: document.getElementById("act-type").value, memo: document.getElementById("act-memo").value }; try { let res; if (id) { res = await fetch(`${API_BASE}/activities/${id}`, { method: "PUT", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); } else { res = await fetch(`${API_BASE}/activities`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload) }); } if (!res.ok) throw new Error("Activity save API error"); document.getElementById("activity-modal").style.display = "none"; showSupplierDetail(selectedSupplierId); } catch (err) { console.error(err); alert("일지 저장에 실패했습니다."); } } window.deleteActivity = async function(actId) { if (!confirm("이 매입 일지를 삭제하시겠습니까?")) return; try { const res = await fetch(`${API_BASE}/activities/${actId}`, { method: "DELETE" }); if (!res.ok) throw new Error("Failed to delete activity"); showSupplierDetail(selectedSupplierId); } catch (err) { console.error(err); alert("일지 삭제에 실패했습니다."); } };