/* GUARDiA 고객 포털 JS */ let currentSrId = null; let selectedStar = 0; let pollTimer = null; const STATUS_LABEL = { RECEIVED: "접수됨", PARSED: "분석 중", PENDING_APPROVAL: "승인 대기", APPROVED: "승인됨", IN_PROGRESS: "처리 중", PENDING_PM_VALIDATION: "PM 검증", COMPLETED: "처리 완료", FAILED_ROLLBACK: "처리 실패", REJECTED: "반려", }; const ACTION_LABEL = { CMDB_CHECK: "🔍 자산 확인", SSH_CONNECT: "🔗 서버 접속", SSH_EXEC: "⚡ 명령 실행", SOURCE_MOD: "📦 파일 배포", HEALTH_CHECK: "💓 헬스 체크", RESULT: "📋 결과 기록", COMPLETE: "✅ 완료 처리", }; /* ── 폼 제출 ── */ document.getElementById("sr-form").addEventListener("submit", async e => { e.preventDefault(); const btn = document.getElementById("submit-btn"); const label = document.getElementById("submit-label"); const spinner = document.getElementById("submit-spinner"); btn.disabled = true; label.textContent = "등록 중…"; spinner.classList.remove("hidden"); const fd = new FormData(e.target); const payload = Object.fromEntries(fd.entries()); if (!payload.description) delete payload.description; if (!payload.target_server) delete payload.target_server; try { const res = await fetch("/api/tasks", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(payload), }); if (!res.ok) throw new Error((await res.json()).detail || "오류 발생"); const sr = await res.json(); currentSrId = sr.sr_id; document.getElementById("result-sr-id").textContent = sr.sr_id; document.getElementById("section-form").classList.add("hidden"); document.getElementById("section-result").classList.remove("hidden"); await refreshStatus(); pollTimer = setInterval(refreshStatus, 5000); // 5초마다 갱신 } catch (err) { alert("요청 등록 실패: " + err.message); btn.disabled = false; label.textContent = "요청 등록하기"; spinner.classList.add("hidden"); } }); /* ── 상태 폴링 ── */ async function refreshStatus() { if (!currentSrId) return; const [srRes, workRes, ratingRes] = await Promise.all([ fetch(`/api/tasks/${currentSrId}`).then(r => r.ok ? r.json() : null), fetch(`/api/work/${currentSrId}`).then(r => r.ok ? r.json() : []), fetch(`/api/rating/${currentSrId}`).then(r => r.ok ? r.json() : null).catch(() => null), ]); if (!srRes) return; /* 상태 배지 */ document.getElementById("status-badge-row").innerHTML = `${STATUS_LABEL[srRes.status] || srRes.status}`; /* 작업 타임라인 */ const tl = document.getElementById("work-timeline"); if (workRes.length) { tl.innerHTML = workRes.map(w => `
${ACTION_LABEL[w.action_type] || w.action_type}
${esc(w.content || "")}${w.result ? " → " + esc(w.result.slice(0, 80)) : ""}
`).join(""); } else { tl.innerHTML = `
처리 대기 중입니다…
`; } /* 완료 시: 별점 섹션 표시 */ if (srRes.status === "COMPLETED") { clearInterval(pollTimer); if (!ratingRes) { document.getElementById("rating-section").classList.remove("hidden"); } else { showRatingDone(ratingRes.stars); } } } /* ── 별점 선택 ── */ function setStar(n) { selectedStar = n; document.querySelectorAll(".star-btn").forEach((btn, i) => { btn.classList.toggle("active", i < n); }); document.getElementById("btn-rate").disabled = false; } /* ── 별점 제출 ── */ async function submitRating() { if (!selectedStar || !currentSrId) return; const comment = document.getElementById("rating-comment").value.trim(); const customer = document.getElementById("f-name")?.value || document.getElementById("result-sr-id")?.textContent || "고객"; const res = await fetch(`/api/rating/${currentSrId}`, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ customer, stars: selectedStar, comment: comment || null }), }); if (res.ok) { showRatingDone(selectedStar); } } function showRatingDone(stars) { document.getElementById("rating-section").classList.remove("hidden"); document.querySelector(".stars-row").classList.add("hidden"); document.querySelector(".rating-comment-input").classList.add("hidden"); document.getElementById("btn-rate").classList.add("hidden"); const done = document.getElementById("rating-done"); done.classList.remove("hidden"); done.textContent = `${"★".repeat(stars)}${"☆".repeat(5 - stars)} — 감사합니다! 소중한 의견이 반영됩니다 🙏`; } /* ── 초기화 ── */ function resetForm() { clearInterval(pollTimer); currentSrId = null; selectedStar = 0; document.getElementById("sr-form").reset(); document.getElementById("section-form").classList.remove("hidden"); document.getElementById("section-result").classList.add("hidden"); document.getElementById("rating-section").classList.add("hidden"); document.getElementById("rating-done").classList.add("hidden"); document.getElementById("work-timeline").innerHTML = "
처리 정보를 불러오는 중…
"; } function esc(s) { return String(s ?? "").replace(/&/g,"&").replace(//g,">"); }