import { API_BASE_URL } from "@config/config_frontend"; type Source = { path: string; excerpt: string }; type ChatAnswer = { answer: string; sources: Source[]; detail?: string }; export function buildKnowledgeChat(): HTMLElement { const wrap = document.createElement("div"); wrap.className = "b01-knowledge-chat"; const toggle = document.createElement("button"); toggle.type = "button"; toggle.className = "b01-knowledge-chat__toggle"; toggle.textContent = "원문 안내"; toggle.setAttribute("aria-expanded", "false"); const panel = document.createElement("section"); panel.className = "b01-knowledge-chat__panel"; panel.hidden = true; panel.setAttribute("aria-label", "지식DB 원문 안내 채팅"); const header = document.createElement("header"); header.textContent = "지식DB 원문 안내"; const messages = document.createElement("div"); messages.className = "b01-knowledge-chat__messages"; messages.setAttribute("role", "log"); messages.setAttribute("aria-live", "polite"); const form = document.createElement("form"); form.className = "b01-knowledge-chat__form"; const input = document.createElement("input"); input.type = "text"; input.required = true; input.maxLength = 500; input.placeholder = "법령·지침을 질문하세요"; input.setAttribute("aria-label", "질문"); const submit = document.createElement("button"); submit.type = "submit"; submit.textContent = "보내기"; form.append(input, submit); panel.append(header, messages, form); wrap.append(toggle, panel); toggle.addEventListener("click", () => { panel.hidden = !panel.hidden; toggle.setAttribute("aria-expanded", String(!panel.hidden)); if (!panel.hidden) input.focus(); }); form.addEventListener("submit", async (event) => { event.preventDefault(); const question = input.value.trim(); if (question.length < 2) return; const userLine = document.createElement("p"); userLine.className = "b01-knowledge-chat__user"; userLine.textContent = question; messages.append(userLine); input.value = ""; input.disabled = submit.disabled = true; const reply = document.createElement("div"); reply.className = "b01-knowledge-chat__reply"; reply.textContent = "원문을 찾는 중입니다…"; messages.append(reply); messages.scrollTop = messages.scrollHeight; try { const response = await fetch(`${API_BASE_URL}/dashboard/knowledge-chat`, { method: "POST", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ question }), }); const result = (await response.json()) as ChatAnswer; if (!response.ok) throw new Error(result.detail || "답변을 받지 못했습니다."); reply.textContent = result.answer; if (result.sources.length) { const sources = document.createElement("details"); const summary = document.createElement("summary"); summary.textContent = `근거 원문 ${result.sources.length}건`; sources.append(summary); result.sources.forEach((source, index) => { const item = document.createElement("details"); const title = document.createElement("summary"); title.textContent = `[${index + 1}] ${source.path}`; const excerpt = document.createElement("pre"); excerpt.textContent = source.excerpt; item.append(title, excerpt); sources.append(item); }); reply.append(sources); } } catch (error) { reply.textContent = error instanceof Error ? error.message : "답변을 받지 못했습니다."; } finally { input.disabled = submit.disabled = false; input.focus(); messages.scrollTop = messages.scrollHeight; } }); return wrap; }