/** * 관리자 UI용: 동일 location 항목을 부모 기준 트리 래퍼로 만든다(항목 객체는 원본 참조). * @param {Array} flat - 전체 항목 * @param {'primary'|'footer'} location - 위치 * @returns {Array<{ item: Object, children: Array<{ item: Object, children: any[] }> }>} */ export const buildNavigationEditorTree = (flat, location) => { const filtered = flat.filter((i) => i.location === location) const nodeMap = new Map() for (const item of filtered) { nodeMap.set(String(item.id).trim(), { item, children: [] }) } const roots = [] for (const item of filtered) { const id = String(item.id).trim() const wrap = nodeMap.get(id) const p = item.parentId if (p != null && String(p).trim() !== '') { const pid = String(p).trim() if (nodeMap.has(pid)) { nodeMap.get(pid).children.push(wrap) continue } } roots.push(wrap) } /** * @param {Array<{ item: Object, children: any[] }>} nodes - 노드 * @returns {void} */ const sortRec = (nodes) => { nodes.sort((a, b) => (a.item.sortOrder || 0) - (b.item.sortOrder || 0)) for (const n of nodes) { sortRec(n.children) } } sortRec(roots) return roots } /** * 관리자 상단 네비 트리 래퍼를 표시·드래그용 평면 행 배열로 만든다. * @param {Array<{ item: Object, children: any[] }>} wraps - `buildNavigationEditorTree` 결과 * @param {number} [depth] - 들여쓰기 단계(0=루트) * @returns {Array<{ item: Object, depth: number }>} */ export const flattenNavigationEditorWrappers = (wraps, depth = 0) => { const out = [] if (!Array.isArray(wraps)) { return out } for (const w of wraps) { if (!w?.item) { continue } out.push({ item: w.item, depth }) if (w.children?.length) { out.push(...flattenNavigationEditorWrappers(w.children, depth + 1)) } } return out }