관리자 미디어 필터 입력 공통화

This commit is contained in:
2026-07-23 17:05:54 +09:00
parent 24e3d516b3
commit 30e5071cba
8 changed files with 121 additions and 61 deletions

View File

@@ -23,7 +23,10 @@ definePageMeta({
const MEDIA_THUMBNAIL_ROOT = '썸네일'
/** 관리자 미디어 한 페이지 표시 개수 옵션 */
const mediaPageSizeOptions = [50, 100, 200]
const mediaPageSizeOptions = [50, 100, 200].map((size) => ({
value: size,
label: `${size}개`
}))
/** 회원 등급 코드 → 미디어 배지 라벨 */
const memberRoleBadgeLabels = {
@@ -489,11 +492,11 @@ const mediaKindFilterOptions = computed(() => {
const countByKind = mediaCounts.value.kinds || {}
return [
{ id: 'all', label: '전체', count: countByKind.all || 0 },
{ id: 'image', label: '이미지', count: countByKind.image || 0 },
{ id: 'video', label: '영상', count: countByKind.video || 0 },
{ id: 'audio', label: '음악', count: countByKind.audio || 0 },
{ id: 'file', label: '파일', count: countByKind.file || 0 }
{ value: 'all', label: '전체', count: countByKind.all || 0 },
{ value: 'image', label: '이미지', count: countByKind.image || 0 },
{ value: 'video', label: '영상', count: countByKind.video || 0 },
{ value: 'audio', label: '음악', count: countByKind.audio || 0 },
{ value: 'file', label: '파일', count: countByKind.file || 0 }
]
})
@@ -501,8 +504,8 @@ const mediaUsageFilterOptions = computed(() => {
const usageCounts = mediaCounts.value.usage || {}
return [
{ id: 'all', label: '전체', count: usageCounts.all || 0, unusedOnly: false },
{ id: 'unused', label: '미사용', count: usageCounts.unused || 0, unusedOnly: true }
{ value: false, id: 'all', label: '전체', count: usageCounts.all || 0 },
{ value: true, id: 'unused', label: '미사용', count: usageCounts.unused || 0 }
]
})
@@ -676,11 +679,11 @@ const setMediaPage = (page) => {
/**
* 관리자 미디어 페이지 표시 개수를 변경한다.
* @param {Event} event - select 변경 이벤트
* @param {number} pageSize - 변경할 표시 개수
* @returns {void}
*/
const setMediaPageSize = (event) => {
mediaPageSize.value = Number(event.target.value) || 50
const setMediaPageSize = (pageSize) => {
mediaPageSize.value = Number(pageSize) || 50
mediaPage.value = 1
clearMediaSelection()
closeMediaDetail()
@@ -1411,31 +1414,21 @@ watch(() => mediaPagination.value.page, (page) => {
</div>
<div class="admin-media__filters flex flex-wrap gap-1.5">
<template v-if="activeTab === 'library'">
<button
v-for="option in mediaKindFilterOptions"
:key="option.id"
class="admin-media__kind-filter rounded-full border px-3 py-1.5 text-xs font-semibold transition"
:class="activeMediaKind === option.id ? 'border-[#15171a] bg-[#15171a] text-white' : 'border-line bg-white text-muted hover:text-ink'"
type="button"
@click="setMediaKindFilter(option.id)"
>
{{ option.label }}
<span class="ml-1 opacity-70">{{ option.count }}</span>
</button>
</template>
<button
v-for="option in visibleMediaUsageFilterOptions"
:key="`usage-${option.id}`"
class="admin-media__usage-filter rounded-full border px-3 py-1.5 text-xs font-semibold transition"
:class="showUnusedOnly === option.unusedOnly ? 'border-[#15171a] bg-[#15171a] text-white' : 'border-line bg-white text-muted hover:text-ink'"
type="button"
:aria-pressed="showUnusedOnly === option.unusedOnly"
@click="setMediaUsageFilter(option.unusedOnly)"
>
{{ option.label }}
<span class="ml-1 opacity-70">{{ option.count }}</span>
</button>
<AdminFilterPillGroup
v-if="activeTab === 'library'"
:model-value="activeMediaKind"
:options="mediaKindFilterOptions"
label="미디어 종류 필터"
button-class="admin-media__kind-filter"
@update:model-value="setMediaKindFilter"
/>
<AdminFilterPillGroup
:model-value="showUnusedOnly"
:options="visibleMediaUsageFilterOptions"
label="미디어 사용 상태 필터"
button-class="admin-media__usage-filter"
@update:model-value="setMediaUsageFilter"
/>
</div>
</div>
@@ -1536,24 +1529,17 @@ watch(() => mediaPagination.value.page, (page) => {
</p>
</div>
<div class="admin-media__selection-actions flex flex-wrap items-center justify-end gap-2">
<label v-if="filteredMediaItems.length" class="admin-media__page-size flex items-center gap-2 text-xs font-semibold text-muted">
<div v-if="filteredMediaItems.length" class="admin-media__page-size flex items-center gap-2 text-xs font-semibold text-muted">
<span>표시</span>
<span class="admin-media__page-size-select-wrap relative inline-flex">
<select
class="admin-media__page-size-select appearance-none rounded border border-line bg-white py-2 pl-2 pr-8 text-xs font-semibold text-ink outline-none transition focus:border-[#8e9cac]"
:value="mediaPageSize"
@change="setMediaPageSize"
>
<option v-for="size in mediaPageSizeOptions" :key="size" :value="size">
{{ size }}개
</option>
</select>
<svg xmlns="http://www.w3.org/2000/svg" class="icon icon-tabler icon-tabler-chevron-down pointer-events-none absolute right-2 top-1/2 size-4 -translate-y-1/2 text-[#15171a]" width="24" height="24" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<polyline points="6 9 12 15 18 9" />
</svg>
</span>
</label>
<AdminSelectInput
:model-value="mediaPageSize"
:options="mediaPageSizeOptions"
label="미디어 표시 개수"
root-class="admin-media__page-size-select-wrap inline-flex"
select-class="admin-media__page-size-select py-2 pl-2 pr-8 text-xs font-semibold text-ink"
@update:model-value="setMediaPageSize"
/>
</div>
<button
v-if="filteredMediaItems.length"
class="admin-media__select-all rounded border border-line bg-white px-3 py-2 text-xs font-semibold text-ink transition hover:border-[#c8ced3] disabled:cursor-not-allowed disabled:opacity-50"