관리자 미디어 오류 피드백을 useAdminToast 토스트로 통일 (v0.0.93)

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-05-12 11:03:23 +09:00
parent c1242e1409
commit 4de5589bcb
8 changed files with 89 additions and 26 deletions

View File

@@ -23,12 +23,13 @@ const editingUrl = ref('')
const editingName = ref('')
const editingCategory = ref('')
const deletingUrl = ref('')
const errorMessage = ref('')
const selectedMediaUrl = ref('')
const selectedMediaUrls = ref([])
const lastSelectedIndex = ref(-1)
const draggingUrls = ref([])
const { toast, showToast } = useAdminToast()
const { data: mediaItems, refresh } = await useFetch('/admin/api/media', {
default: () => []
})
@@ -255,7 +256,6 @@ const openMediaDetail = (item) => {
editingUrl.value = item.url
editingName.value = item.title
editingCategory.value = item.category
errorMessage.value = ''
}
/**
@@ -282,7 +282,6 @@ const cancelRename = () => {
*/
const openCreateFolderModal = () => {
createFolderModalName.value = ''
errorMessage.value = ''
isCreateFolderModalOpen.value = true
}
@@ -310,8 +309,6 @@ const submitCreateFolderModal = async () => {
return
}
errorMessage.value = ''
try {
const folderPath = activeFolder.value ? `${activeFolder.value}/${folderName}` : folderName
const createdFolder = await $fetch('/admin/api/media-folders', {
@@ -325,7 +322,7 @@ const submitCreateFolderModal = async () => {
activeFolder.value = createdFolder.path
await refreshMediaFolders()
} catch (error) {
errorMessage.value = error?.data?.message || '폴더를 만들지 못했습니다.'
showToast('error', error?.data?.message || '폴더를 만들지 못했습니다.')
}
}
@@ -344,7 +341,6 @@ const removeMediaFolder = async (folder) => {
}
deletingFolder.value = folder
errorMessage.value = ''
try {
await $fetch('/admin/api/media-folders', {
@@ -363,7 +359,7 @@ const removeMediaFolder = async (folder) => {
refreshMediaFolders()
])
} catch (error) {
errorMessage.value = error?.data?.message || '폴더를 삭제하지 못했습니다.'
showToast('error', error?.data?.message || '폴더를 삭제하지 못했습니다.')
} finally {
deletingFolder.value = ''
}
@@ -386,8 +382,6 @@ const moveMediaToFolder = async (folder, urls = selectedMediaUrls.value) => {
return
}
errorMessage.value = ''
try {
await $fetch('/admin/api/media', {
method: 'PUT',
@@ -403,7 +397,7 @@ const moveMediaToFolder = async (folder, urls = selectedMediaUrls.value) => {
activeFolder.value = folder || '미분류'
clearMediaSelection()
} catch (error) {
errorMessage.value = error?.data?.message || '미디어 폴더를 변경하지 못했습니다.'
showToast('error', error?.data?.message || '미디어 폴더를 변경하지 못했습니다.')
}
}
@@ -455,8 +449,6 @@ const saveMediaCategory = async () => {
return
}
errorMessage.value = ''
try {
await $fetch('/admin/api/media', {
method: 'PUT',
@@ -470,7 +462,7 @@ const saveMediaCategory = async () => {
refreshMediaFolders()
])
} catch (error) {
errorMessage.value = error?.data?.message || '카테고리를 저장하지 못했습니다.'
showToast('error', error?.data?.message || '카테고리를 저장하지 못했습니다.')
}
}
@@ -482,12 +474,10 @@ const renameMedia = async () => {
const editingItem = mediaItems.value.find((item) => item.url === editingUrl.value)
if (editingItem && isMediaItemLocked(editingItem)) {
errorMessage.value = '게시물·페이지에서 쓰이거나, 회원 프로필에 연결된 썸네일은 파일명을 바꿀 수 없습니다.'
showToast('error', '게시물·페이지에서 쓰이거나, 회원 프로필에 연결된 썸네일은 파일명을 바꿀 수 없습니다.')
return
}
errorMessage.value = ''
try {
const renamedItem = await $fetch('/admin/api/media', {
method: 'PUT',
@@ -500,7 +490,7 @@ const renameMedia = async () => {
await refresh()
selectedMediaUrl.value = renamedItem.url
} catch (error) {
errorMessage.value = error?.data?.message || '파일명을 변경하지 못했습니다.'
showToast('error', error?.data?.message || '파일명을 변경하지 못했습니다.')
}
}
@@ -511,7 +501,7 @@ const renameMedia = async () => {
*/
const deleteMedia = async (item) => {
if (isMediaItemLocked(item)) {
errorMessage.value = '게시물·페이지에서 쓰이거나, 회원 프로필에 연결된 썸네일은 삭제할 수 없습니다.'
showToast('error', '게시물·페이지에서 쓰이거나, 회원 프로필에 연결된 썸네일은 삭제할 수 없습니다.')
return
}
@@ -520,7 +510,6 @@ const deleteMedia = async (item) => {
}
deletingUrl.value = item.url
errorMessage.value = ''
try {
await $fetch('/admin/api/media', {
@@ -532,7 +521,7 @@ const deleteMedia = async (item) => {
closeMediaDetail()
await refresh()
} catch (error) {
errorMessage.value = error?.data?.message || '파일을 삭제하지 못했습니다.'
showToast('error', error?.data?.message || '파일을 삭제하지 못했습니다.')
} finally {
deletingUrl.value = ''
}
@@ -578,10 +567,6 @@ const deleteMedia = async (item) => {
</div>
</div>
<p v-if="errorMessage" class="admin-media__error mt-6 rounded border border-red-200 bg-red-50 px-4 py-3 text-sm text-red-700">
{{ errorMessage }}
</p>
<div class="admin-media__layout mt-8 grid gap-5 lg:grid-cols-[16rem_minmax(0,1fr)]">
<aside
v-if="activeTab === 'library'"
@@ -948,5 +933,18 @@ const deleteMedia = async (item) => {
</aside>
</section>
</div>
<div
v-if="toast"
class="admin-media__toast fixed right-5 top-5 z-[100] max-w-[min(24rem,calc(100vw-2.5rem))] rounded border px-4 py-3 text-sm font-semibold shadow-lg"
:class="{
'border-green-200 bg-green-50 text-green-800': toast.type === 'success',
'border-red-200 bg-red-50 text-red-800': toast.type === 'error',
'border-line bg-white text-ink': toast.type === 'info'
}"
role="status"
>
{{ toast.message }}
</div>
</section>
</template>