관리자 글 목록 고정 기능 추가

This commit is contained in:
2026-07-03 15:19:41 +09:00
parent 55efae810f
commit 288e73c0dc
11 changed files with 160 additions and 16 deletions

View File

@@ -59,6 +59,7 @@ const mapPostRow = (row) => ({
featuredImageThumbnail: getExistingPostThumbnailUrl(row.featured_image),
showFeaturedImage: Boolean(row.show_featured_image),
isFeatured: Boolean(row.is_featured),
adminPinned: Boolean(row.admin_pinned),
commentCount: Number(row.comment_count || 0),
totalViews: Number(row.total_views || 0),
seoTitle: row.seo_title || '',
@@ -98,6 +99,7 @@ const mapAdminPostSummaryRow = (row) => ({
featuredImageThumbnail: getExistingPostThumbnailUrl(row.featured_image),
showFeaturedImage: Boolean(row.show_featured_image),
isFeatured: Boolean(row.is_featured),
adminPinned: Boolean(row.admin_pinned),
commentCount: Number(row.comment_count || 0),
totalViews: Number(row.total_views || 0),
status: row.status,
@@ -574,6 +576,10 @@ export const listAdminPosts = async (options = {}) => {
return matchesStatus && matchesTag && matchesFeatured && matchesSearch
})
samplePosts.sort((left, right) => {
if (Boolean(left.adminPinned) !== Boolean(right.adminPinned)) {
return left.adminPinned ? -1 : 1
}
const leftTime = new Date(left.sortAt || 0).getTime()
const rightTime = new Date(right.sortAt || 0).getTime()
@@ -597,7 +603,8 @@ export const listAdminPosts = async (options = {}) => {
},
counts: {
total: getSamplePosts().length,
featured: getSamplePosts().filter((post) => post.isFeatured).length
featured: getSamplePosts().filter((post) => post.isFeatured).length,
pinned: getSamplePosts().filter((post) => post.adminPinned).length
}
}
}
@@ -612,6 +619,7 @@ export const listAdminPosts = async (options = {}) => {
posts.featured_image,
posts.show_featured_image,
posts.is_featured,
posts.admin_pinned,
posts.status,
posts.published_at,
posts.created_at,
@@ -680,11 +688,13 @@ export const listAdminPosts = async (options = {}) => {
posts.featured_image,
posts.show_featured_image,
posts.is_featured,
posts.admin_pinned,
posts.status,
posts.published_at,
posts.created_at,
posts.updated_at
ORDER BY
posts.admin_pinned DESC,
CASE WHEN ${normalizedSortOrder} = 'oldest' THEN COALESCE(posts.published_at, posts.updated_at) END ASC,
CASE WHEN ${normalizedSortOrder} <> 'oldest' THEN COALESCE(posts.published_at, posts.updated_at) END DESC,
posts.id DESC
@@ -699,7 +709,8 @@ export const listAdminPosts = async (options = {}) => {
const countsRows = await sql`
SELECT
COUNT(*)::int AS total,
COUNT(*) FILTER (WHERE posts.is_featured = true)::int AS featured
COUNT(*) FILTER (WHERE posts.is_featured = true)::int AS featured,
COUNT(*) FILTER (WHERE posts.admin_pinned = true)::int AS pinned
FROM posts
`
@@ -759,7 +770,8 @@ export const listAdminPosts = async (options = {}) => {
},
counts: {
total: Number(countsRows[0]?.total || 0),
featured: Number(countsRows[0]?.featured || 0)
featured: Number(countsRows[0]?.featured || 0),
pinned: Number(countsRows[0]?.pinned || 0)
}
}
}
@@ -944,6 +956,31 @@ export const updateAdminPostFeatured = async (id, isFeatured) => {
return rows[0] ? getAdminPostById(rows[0].id) : null
}
/**
* 관리자 게시물 고정 상태 수정
* @param {string} id - 게시물 ID
* @param {boolean} adminPinned - 관리자 목록 상단 고정 여부
* @returns {Promise<Object | null>} 수정된 게시물
*/
export const updateAdminPostPinned = async (id, adminPinned) => {
const sql = getPostgresClient()
if (!sql) {
throw new Error('DATABASE_REQUIRED')
}
const rows = await sql`
UPDATE posts
SET
admin_pinned = ${Boolean(adminPinned)},
updated_at = now()
WHERE id = ${id}
RETURNING id
`
return rows[0] ? getAdminPostById(rows[0].id) : null
}
/**
* 관리자 게시물 삭제
* @param {string} id - 게시물 ID