/** * 지식 탐색 서랍(Drawer) 관리 모듈 */ import { escapeHTML } from '../utils.js'; import { I18nManager } from '../utils/I18nManager.js'; import { Constants } from '../utils/Constants.js'; export const DrawerManager = { DOM: {}, init() { this.DOM.drawer = document.getElementById('knowledgeDrawer'); this.DOM.drawerContent = document.getElementById('drawerContent'); const header = this.DOM.drawer?.querySelector('.drawer-header'); if (!this.DOM.drawer || !header) return; // 닫기 버튼 이벤트 const closeBtn = document.getElementById('closeDrawerBtn'); if (closeBtn) { closeBtn.onclick = () => this.close(); } // --- 드래그 앤 드롭 로직 구현 --- let isDragging = false; let offset = { x: 0, y: 0 }; header.addEventListener('mousedown', (e) => { if (e.target.closest('.close-btn')) return; // 닫기 버튼 클릭 시 드래그 방지 isDragging = true; this.DOM.drawer.classList.add('dragging'); // 마우스 클릭 위치와 요소 좌상단 사이의 거리 계산 const rect = this.DOM.drawer.getBoundingClientRect(); offset.x = e.clientX - rect.left; offset.y = e.clientY - rect.top; }); document.addEventListener('mousemove', (e) => { if (!isDragging) return; e.preventDefault(); // 새로운 위치 계산 let left = e.clientX - offset.x; let top = e.clientY - offset.y; // 화면 경계 이탈 방지 const winW = window.innerWidth; const winH = window.innerHeight; const cardW = this.DOM.drawer.offsetWidth; const cardH = this.DOM.drawer.offsetHeight; left = Math.max(0, Math.min(left, winW - cardW)); top = Math.max(0, Math.min(top, winH - cardH)); this.DOM.drawer.style.left = `${left}px`; this.DOM.drawer.style.top = `${top}px`; this.DOM.drawer.style.bottom = 'auto'; // bottom 제거 }); document.addEventListener('mouseup', () => { isDragging = false; this.DOM.drawer?.classList.remove('dragging'); }); }, open(memos = [], activeFilter, onFilterCallback) { if (!this.DOM.drawer || !this.DOM.drawerContent) return; // 0. 데이터 유효성 검사 if (!memos || memos.length === 0) { this.DOM.drawerContent.innerHTML = `
${I18nManager.t('label_no_results')}
`; this.DOM.drawer.classList.add('active'); return; } // 1. 그룹 및 태그 카운트 계산 const groupAllKey = 'all'; const groupCounts = { [groupAllKey]: memos.length }; const tagCounts = {}; const tagsSourceMap = new Map(); memos.forEach(m => { const g = m.group_name || Constants.GROUPS.DEFAULT; groupCounts[g] = (groupCounts[g] || 0) + 1; if (m.tags) { m.tags.forEach(t => { tagCounts[t.name] = (tagCounts[t.name] || 0) + 1; const current = tagsSourceMap.get(t.name); if (!current || t.source === 'user') tagsSourceMap.set(t.name, t.source); }); } }); const sortedGroups = Object.keys(groupCounts).filter(g => g !== groupAllKey).sort(); const sortedTags = Object.keys(tagCounts).sort().map(tn => ({ name: tn, source: tagsSourceMap.get(tn), count: tagCounts[tn] })); // 2. HTML 렌더링 let html = `