메뉴 관리: 탭 분리·드래그 정렬·상단 트리·공개 접기 (v0.0.94)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-12 11:16:43 +09:00
parent 4de5589bcb
commit bcff96aa4c
19 changed files with 1146 additions and 181 deletions

View File

@@ -5,7 +5,8 @@ import {
getSamplePosts,
getSampleTags
} from '../utils/sample-content'
import { getDefaultNavigationItems, groupNavigationItems } from '../utils/navigation-items'
import { getDefaultNavigationItems } from '../utils/navigation-items'
import { buildPublicPrimaryTree, orderNavigationItemsForInsert } from '../utils/navigation-tree'
import { getDefaultSiteSettings } from '../utils/site-settings'
import { getPostgresClient } from './postgres-client'
@@ -89,6 +90,8 @@ const mapNavigationItemRow = (row) => ({
location: row.location,
sortOrder: row.sort_order,
isVisible: row.is_visible,
parentId: row.parent_id ?? null,
isFolder: Boolean(row.is_folder),
createdAt: row.created_at.toISOString(),
updatedAt: row.updated_at.toISOString()
})
@@ -806,7 +809,23 @@ export const listNavigationItems = async ({ visibleOnly = false } = {}) => {
* 공개 네비게이션 조회
* @returns {Promise<{primary: Array<Object>, footer: Array<Object>}>} 위치별 공개 네비게이션
*/
export const getPublicNavigation = async () => groupNavigationItems(await listNavigationItems({ visibleOnly: true }))
export const getPublicNavigation = async () => {
const flat = await listNavigationItems({ visibleOnly: true })
const primaryFlat = flat.filter((item) => item.location === 'primary')
const footerFlat = flat
.filter((item) => item.location === 'footer' && !item.parentId)
.sort((a, b) => (a.sortOrder || 0) - (b.sortOrder || 0))
return {
primary: buildPublicPrimaryTree(primaryFlat),
footer: footerFlat.map((item) => ({
id: item.id,
label: item.label,
url: item.url,
isVisible: item.isVisible
}))
}
}
/**
* 관리자 네비게이션 항목 일괄 저장
@@ -825,21 +844,28 @@ export const updateNavigationItems = async (items) => {
DELETE FROM navigation_items
`
for (const item of items) {
const ordered = orderNavigationItemsForInsert(items)
for (const item of ordered) {
await transaction`
INSERT INTO navigation_items (
id,
label,
url,
location,
sort_order,
is_visible
is_visible,
parent_id,
is_folder
)
VALUES (
${item.id},
${item.label},
${item.url},
${item.location},
${item.sortOrder},
${item.isVisible}
${item.isVisible},
${item.parentId ?? null},
${Boolean(item.isFolder)}
)
`
}