관리자 목록 more vert 메뉴 통일 및 태그 메뉴 정렬 수정

AdminRowMoreMenu 공통 컴포넌트로 글·태그·페이지·미디어·네비게이션 행 액션을 ⋮ 팝오버로 통일.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-19 14:14:28 +09:00
parent 797a6dd5a0
commit 02d33996c5
10 changed files with 540 additions and 106 deletions

View File

@@ -9,6 +9,8 @@ const saving = ref(false)
const activeTab = ref('primary')
const { toast, showToast, clearToast } = useAdminToast()
const { openMenuId, closeMenu } = useAdminRowMenu()
const { data: navigationItems } = await useFetch('/admin/api/navigation', {
default: () => []
})
@@ -118,6 +120,16 @@ const removeItemCascade = (rootId) => {
items.value = items.value.filter((i) => !toRemove.has(String(i.id)))
}
/**
* 메뉴 항목을 삭제한다(하위 포함).
* @param {string} itemId - 항목 id
* @returns {void}
*/
const removeNavItem = (itemId) => {
closeMenu()
removeItemCascade(itemId)
}
/**
* 항목 id로 레코드를 찾는다.
* @param {string} id - 항목 id
@@ -750,7 +762,7 @@ const saveNavigation = async () => {
상단 메뉴가 없습니다. 버튼으로 항목을 추가하세요.
</div>
<div v-else class="admin-navigation__primary-table overflow-hidden rounded border border-line bg-white">
<div v-else class="admin-navigation__primary-table overflow-x-auto rounded border border-line bg-white">
<table class="admin-navigation__primary-table-inner w-full border-collapse text-left text-sm">
<thead class="admin-navigation__primary-head bg-[#f5f5f2] text-xs uppercase text-muted">
<tr>
@@ -763,8 +775,8 @@ const saveNavigation = async () => {
<th class="admin-navigation__primary-cell px-4 py-3">
URL
</th>
<th class="admin-navigation__primary-cell px-4 py-3">
관리
<th class="admin-navigation__primary-cell admin-navigation__cell-actions w-12 px-2 py-3 text-right">
<span class="sr-only">관리</span>
</th>
</tr>
</thead>
@@ -817,14 +829,21 @@ const saveNavigation = async () => {
required
>
</td>
<td class="admin-navigation__primary-cell px-4 py-3 align-middle">
<button
class="admin-navigation__primary-remove rounded border border-red-200 px-3 py-1.5 text-xs font-semibold text-red-700"
type="button"
@click="removeItemCascade(row.item.id)"
<td class="admin-navigation__primary-cell admin-navigation__cell-actions relative w-12 px-2 py-3 text-right align-middle">
<AdminRowMoreMenu
v-model:open-menu-id="openMenuId"
:item-id="`nav-${row.item.id}`"
menu-label="메뉴 항목 메뉴"
>
삭제
</button>
<button
class="admin-row-more-menu__item admin-row-more-menu__item--danger"
type="button"
role="menuitem"
@click="removeNavItem(row.item.id)"
>
메뉴 항목 삭제
</button>
</AdminRowMoreMenu>
</td>
</tr>
</tbody>
@@ -847,7 +866,7 @@ const saveNavigation = async () => {
하단 메뉴가 없습니다.
</div>
<div v-else class="admin-navigation__footer-table overflow-hidden rounded border border-line">
<div v-else class="admin-navigation__footer-table overflow-x-auto rounded border border-line">
<table class="admin-navigation__footer-table-inner w-full border-collapse text-left text-sm">
<thead class="admin-navigation__footer-head bg-[#f5f5f2] text-xs uppercase text-muted">
<tr>
@@ -860,8 +879,8 @@ const saveNavigation = async () => {
<th class="admin-navigation__footer-cell px-4 py-3">
URL
</th>
<th class="admin-navigation__footer-cell px-4 py-3">
관리
<th class="admin-navigation__footer-cell admin-navigation__cell-actions w-12 px-2 py-3 text-right">
<span class="sr-only">관리</span>
</th>
</tr>
</thead>
@@ -898,14 +917,21 @@ const saveNavigation = async () => {
required
>
</td>
<td class="admin-navigation__footer-cell px-4 py-4">
<button
class="rounded border border-red-200 px-3 py-1.5 text-xs font-semibold text-red-700"
type="button"
@click="removeItemCascade(item.id)"
<td class="admin-navigation__footer-cell admin-navigation__cell-actions relative w-12 px-2 py-4 text-right">
<AdminRowMoreMenu
v-model:open-menu-id="openMenuId"
:item-id="`nav-${item.id}`"
menu-label="메뉴 항목 메뉴"
>
삭제
</button>
<button
class="admin-row-more-menu__item admin-row-more-menu__item--danger"
type="button"
role="menuitem"
@click="removeNavItem(item.id)"
>
메뉴 항목 삭제
</button>
</AdminRowMoreMenu>
</td>
</tr>
</tbody>
@@ -931,7 +957,7 @@ const saveNavigation = async () => {
추천 사이트가 없습니다.
</div>
<div v-else class="admin-navigation__recommended-table overflow-hidden rounded border border-line">
<div v-else class="admin-navigation__recommended-table overflow-x-auto rounded border border-line">
<table class="admin-navigation__recommended-table-inner w-full border-collapse text-left text-sm">
<thead class="admin-navigation__recommended-head bg-[#f5f5f2] text-xs uppercase text-muted">
<tr>
@@ -944,8 +970,8 @@ const saveNavigation = async () => {
<th class="admin-navigation__recommended-cell px-4 py-3">
URL
</th>
<th class="admin-navigation__recommended-cell px-4 py-3">
관리
<th class="admin-navigation__recommended-cell admin-navigation__cell-actions w-12 px-2 py-3 text-right">
<span class="sr-only">관리</span>
</th>
</tr>
</thead>
@@ -982,14 +1008,21 @@ const saveNavigation = async () => {
required
>
</td>
<td class="admin-navigation__recommended-cell px-4 py-4">
<button
class="rounded border border-red-200 px-3 py-1.5 text-xs font-semibold text-red-700"
type="button"
@click="removeItemCascade(item.id)"
<td class="admin-navigation__recommended-cell admin-navigation__cell-actions relative w-12 px-2 py-4 text-right">
<AdminRowMoreMenu
v-model:open-menu-id="openMenuId"
:item-id="`nav-${item.id}`"
menu-label="메뉴 항목 메뉴"
>
삭제
</button>
<button
class="admin-row-more-menu__item admin-row-more-menu__item--danger"
type="button"
role="menuitem"
@click="removeNavItem(item.id)"
>
메뉴 항목 삭제
</button>
</AdminRowMoreMenu>
</td>
</tr>
</tbody>