v0.0.87: 저장·로그인 버튼 비활성 기본, 글 목록 삭제 아이콘, 푸시 지침

This commit is contained in:
2026-05-12 10:08:18 +09:00
parent 79fb354d91
commit 1d9a3e4527
11 changed files with 129 additions and 19 deletions

View File

@@ -14,6 +14,28 @@ const { data: navigationItems } = await useFetch('/admin/api/navigation', {
const items = ref(navigationItems.value.map((item) => ({ ...item })))
/**
* 네비게이션 항목을 저장 API와 동일한 형태로 직렬화한다.
* @param {Array<Object>} list - 항목 목록
* @returns {string} 비교용 JSON 문자열
*/
const serializeNavigationItems = (list) => JSON.stringify(list.map((item) => ({
label: String(item.label || '').trim(),
url: String(item.url || '').trim(),
location: item.location,
sortOrder: Number(item.sortOrder || 0),
isVisible: Boolean(item.isVisible)
})))
/** 서버에서 불러온 네비게이션 직렬화 스냅샷 */
const navigationBaseline = ref(serializeNavigationItems(items.value))
/**
* 현재 편집본이 서버 스냅샷과 다른지 여부
* @returns {boolean} 변경 여부
*/
const isNavigationDirty = computed(() => serializeNavigationItems(items.value) !== navigationBaseline.value)
/**
* 저장 상태 토스트 표시
* @param {'success'|'error'|'info'} type - 토스트 타입
@@ -58,6 +80,10 @@ const removeNavigationItem = (index) => {
* @returns {Promise<void>} 저장 결과
*/
const saveNavigation = async () => {
if (saving.value || !isNavigationDirty.value) {
return
}
saving.value = true
errorMessage.value = ''
showToast('info', '네비게이션을 저장하는 중입니다.')
@@ -77,6 +103,7 @@ const saveNavigation = async () => {
})
items.value = savedItems.map((item) => ({ ...item }))
navigationBaseline.value = serializeNavigationItems(items.value)
showToast('success', '네비게이션이 저장되었습니다.')
} catch (error) {
errorMessage.value = error?.data?.message || '네비게이션을 저장하지 못했습니다.'
@@ -184,7 +211,7 @@ onBeforeUnmount(() => {
<button
class="admin-navigation__submit rounded bg-[#15171a] px-4 py-2 text-sm font-semibold text-white disabled:opacity-50"
type="submit"
:disabled="saving"
:disabled="saving || !isNavigationDirty"
>
{{ saving ? '저장 중' : '메뉴 저장' }}
</button>