릴리스: v1.4.0 주제·템플릿 용어 정리 1차

This commit is contained in:
2026-04-02 18:06:02 +09:00
parent 77605791fb
commit 20186f7fe2
12 changed files with 96 additions and 86 deletions

View File

@@ -214,7 +214,7 @@ const customItemTargetGame = computed(() => games.value.find((game) => game.id =
const importModalItemCount = computed(() => importModalItems.value.length)
const activeTabTitle = computed(() => {
if (activeTab.value === 'featured') return '목록 관리'
if (activeTab.value === 'game-admin') return '게임 관리'
if (activeTab.value === 'game-admin') return '템플릿 관리'
if (activeTab.value === 'items') return '아이템 관리'
if (activeTab.value === 'tierlists') {
return tierlistsMode.value === 'requests' ? '템플릿 요청 관리' : '전체 티어표 관리'
@@ -223,17 +223,17 @@ const activeTabTitle = computed(() => {
})
const activeTabDescription = computed(() => {
if (activeTab.value === 'featured') {
return '홈 화면 상단에 고정 노출되는 게임 순서를 따로 관리합니다.'
return '홈 화면 상단에 고정 노출되는 템플릿 순서를 따로 관리합니다.'
}
if (activeTab.value === 'game-admin') {
return '게임 생성, 선택, 썸네일, 기본 아이템 관리를 전용 작업 화면으로 분리했습니다.'
return '템플릿 생성, 선택, 썸네일, 기본 아이템 관리를 전용 작업 화면으로 분리했습니다.'
}
if (activeTab.value === 'items') {
return '사용자 업로드와 관리자 템플릿 이미지를 함께 검수하고, 필요한 게임에 직접 연결할 수 있어요.'
return '사용자 업로드와 관리자 템플릿 이미지를 함께 검수하고, 필요한 템플릿에 직접 연결할 수 있어요.'
}
if (activeTab.value === 'tierlists') {
return tierlistsMode.value === 'requests'
? '사용자 요청을 확인하고, 게임 관리 화면에서 필요한 아이템만 선별 반영한 뒤 직접 완료 처리합니다.'
? '사용자 요청을 확인하고, 템플릿 관리 화면에서 필요한 아이템만 선별 반영한 뒤 직접 완료 처리합니다.'
: '공개/비공개 포함 전체 티어표를 확인하고, 추가 아이템을 템플릿으로 가져올 수 있어요.'
}
return '계정 정보, 권한, 비밀번호와 최근 활동을 더 가볍게 확인하고 수정합니다.'
@@ -245,14 +245,14 @@ const adminOverviewStats = computed(() => {
if (activeTab.value === 'featured') {
return [
{ label: '전체 게임', value: `${games.value.length}` },
{ label: '전체 템플릿', value: `${games.value.length}` },
{ label: '상단 고정', value: `${featuredGameIds.value.length}/50` },
{ label: '추가 가능', value: `${Math.max(0, 50 - featuredGameIds.value.length)}` },
]
}
if (activeTab.value === 'game-admin') {
return [
{ label: '전체 게임', value: `${games.value.length}` },
{ label: '전체 템플릿', value: `${games.value.length}` },
{ label: '티어표 전체', value: `${selectedGameTierListStats.value.total || 0}` },
{ label: '공개', value: `${selectedGameTierListStats.value.publicCount || 0}` },
{ label: '비공개', value: `${selectedGameTierListStats.value.privateCount || 0}` },
@@ -794,7 +794,7 @@ async function refreshGames() {
.map((game) => game.id)
await syncFeaturedSortable()
} catch (e) {
error.value = '게임 목록을 불러오지 못했어요.'
error.value = '템플릿 목록을 불러오지 못했어요.'
}
}
@@ -1275,7 +1275,7 @@ async function removeGame() {
await refreshGames()
success.value = `${deletedName} 게임을 삭제했어요.`
} catch (e) {
error.value = '게임 삭제에 실패했어요.'
error.value = '템플릿 삭제에 실패했어요.'
}
}
@@ -1570,7 +1570,7 @@ async function confirmTierListImport() {
try {
if (importModalMode.value === 'existing') {
if (!importModalTargetGameId.value) {
error.value = '아이템을 추가할 기존 게임을 선택해주세요.'
error.value = '아이템을 추가할 기존 템플릿을 선택해주세요.'
return
}
@@ -1584,7 +1584,7 @@ async function confirmTierListImport() {
const nextGameId = (importModalNewGameId.value || '').trim()
const nextGameName = (importModalNewGameName.value || '').trim()
if (!nextGameId || !nextGameName) {
error.value = '새 게임 ID와 이름을 모두 입력해주세요.'
error.value = '새 템플릿 ID와 이름을 모두 입력해주세요.'
return
}
@@ -1610,9 +1610,9 @@ function templateRequestTypeLabel(request) {
function templateRequestTargetLabel(request) {
if (request.type === 'create') {
if (request.targetGameName || request.targetGameId) {
return `연결된 게임 · ${request.targetGameName || request.targetGameId}`
return `연결된 템플릿 · ${request.targetGameName || request.targetGameId}`
}
return '연결된 게임 없음'
return '연결된 템플릿 없음'
}
return request.targetGameName || request.targetGameId || request.sourceGameName
}
@@ -1787,16 +1787,16 @@ function userAvatarFallback(user) {
<div v-if="gameCreateModalOpen" class="modalOverlay" @click.self="closeGameCreateModal">
<div class="modalCard" role="dialog" aria-modal="true">
<div class="modalCard__title"> 게임 만들기</div>
<div class="modalCard__desc">게임 이름과 고유 ID를 입력한 생성하면 바로 아래 상세 관리 화면으로 이어집니다.</div>
<div class="modalCard__title"> 템플릿 만들기</div>
<div class="modalCard__desc">템플릿 이름과 고유 ID를 입력한 생성하면 바로 아래 상세 관리 화면으로 이어집니다.</div>
<div class="modalCard__form">
<label class="field">
<span class="field__label">게임 이름</span>
<input v-model="newGameName" class="field__input" maxlength="60" placeholder="게임 이름" />
<span class="field__label">템플릿 이름</span>
<input v-model="newGameName" class="field__input" maxlength="60" placeholder="템플릿 이름" />
<span class="field__hint">{{ newGameName.length }}/60</span>
</label>
<label class="field">
<span class="field__label">게임 ID</span>
<span class="field__label">템플릿 ID</span>
<input
v-model="newGameId"
class="field__input"
@@ -1814,7 +1814,7 @@ function userAvatarFallback(user) {
</div>
<div class="modalCard__actions">
<button class="btn btn--ghost" @click="closeGameCreateModal">취소</button>
<button class="btn btn--primary" :disabled="!newGameId.trim() || !newGameName.trim()" @click="createGame">게임 생성</button>
<button class="btn btn--primary" :disabled="!newGameId.trim() || !newGameName.trim()" @click="createGame">템플릿 생성</button>
</div>
</div>
</div>
@@ -1925,14 +1925,14 @@ function userAvatarFallback(user) {
<div v-if="importModalMode === 'existing'" class="modalCard__form">
<select v-model="importModalTargetGameId" class="select">
<option value="">기존 게임 선택</option>
<option value="">기존 템플릿 선택</option>
<option v-for="game in games" :key="game.id" :value="game.id">{{ game.name }}</option>
</select>
</div>
<div v-else class="modalCard__form">
<input v-model="importModalNewGameId" class="input" placeholder="새 게임 ID" />
<input v-model="importModalNewGameName" class="input" placeholder="새 게임 이름" />
<input v-model="importModalNewGameId" class="input" placeholder="새 템플릿 ID" />
<input v-model="importModalNewGameName" class="input" placeholder="새 템플릿 이름" />
</div>
<div class="modalCard__actions">
@@ -1953,12 +1953,12 @@ function userAvatarFallback(user) {
<div class="customItemModal__pickerTitle">템플릿으로 추가할 게임</div>
</div>
<div class="adminSelectionCard">
<div class="adminSelectionCard__label">선택한 게임</div>
<div class="adminSelectionCard__label">선택한 템플릿</div>
<div class="adminSelectionCard__title">{{ customItemTargetGame?.name || '아직 선택하지 않음' }}</div>
<div class="adminSelectionCard__meta">{{ customItemTargetGame?.id || '게임을 골라 주세요.' }}</div>
</div>
<div class="customItemModal__pickerActions">
<button class="btn btn--ghost" type="button" @click="openGamePickerModal('custom-item-target')">게임 선택</button>
<button class="btn btn--ghost" type="button" @click="openGamePickerModal('custom-item-target')">템플릿 선택</button>
<button class="btn btn--ghost btn--small customItemModal__createGameButton" type="button" @click="openGameCreateModal"> 템플릿 만들기</button>
</div>
</aside>
@@ -1991,7 +1991,7 @@ function userAvatarFallback(user) {
<div v-if="visibleLinkedGames.length" class="customItemModal__chips">
<button v-for="game in visibleLinkedGames" :key="game.id" type="button" class="pill pill--link" @click="jumpToGameAdmin(game.id)">{{ game.name }}</button>
</div>
<div v-else class="hint hint--tight">아직 템플릿에 연결된 게임 없어요.</div>
<div v-else class="hint hint--tight">아직 템플릿에 연결된 항목 없어요.</div>
</div>
<div class="customItemModal__actions">
<a class="btn btn--ghost customItemModal__action" :href="toApiUrl(modalTargetCustomItem.src)" :download="modalTargetCustomItem.label">이미지 다운로드</a>
@@ -2010,7 +2010,7 @@ function userAvatarFallback(user) {
<div class="modalCard" role="dialog" aria-modal="true">
<div class="modalCard__titleRow">
<div>
<div class="modalCard__title">게임 선택</div>
<div class="modalCard__title">템플릿 선택</div>
<div class="modalCard__desc">
{{ gamePickerMode === 'tierlists-filter' ? '특정 게임의 티어표만 보려면 게임을 선택하세요.' : '관리할 게임을 검색해서 바로 열 수 있어요.' }}
</div>
@@ -2018,7 +2018,7 @@ function userAvatarFallback(user) {
<button class="btn btn--ghost btn--small" @click="closeGamePickerModal">닫기</button>
</div>
<div class="modalCard__form">
<input v-model="gamePickerQuery" class="input" placeholder="게임 이름 또는 ID 검색" />
<input v-model="gamePickerQuery" class="input" placeholder="템플릿 이름 또는 ID 검색" />
<select v-model="gamePickerSort" class="select">
<option value="recent">최신순</option>
<option value="oldest">오래된순</option>
@@ -2201,7 +2201,7 @@ function userAvatarFallback(user) {
<div class="adminSidebar__label">Mode</div>
<div class="adminSidebar__tabs">
<button class="tab" :class="{ 'tab--active': activeTab === 'featured' }" @click="setTab('featured')">목록 관리</button>
<button class="tab" :class="{ 'tab--active': activeTab === 'game-admin' }" @click="setTab('game-admin')">게임 관리</button>
<button class="tab" :class="{ 'tab--active': activeTab === 'game-admin' }" @click="setTab('game-admin')">템플릿 관리</button>
<button class="tab" :class="{ 'tab--active': activeTab === 'items' }" @click="setTab('items')">아이템 관리</button>
<button class="tab" :class="{ 'tab--active': activeTab === 'tierlists' }" @click="setTab('tierlists')">티어표 관리</button>
<button class="tab" :class="{ 'tab--active': activeTab === 'users' }" @click="setTab('users')">회원 관리</button>
@@ -2209,16 +2209,16 @@ function userAvatarFallback(user) {
</section>
<section v-if="activeTab === 'game-admin'" class="adminSidebar__panel">
<div class="adminSidebar__label">Game</div>
<div class="adminSidebar__label">Template</div>
<div class="adminSidebar__group">
<button class="btn btn--primary" @click="openGameCreateModal"> 게임 생성</button>
<button class="btn btn--ghost" @click="openGamePickerModal('game-admin')">게임 선택</button>
<button class="btn btn--primary" @click="openGameCreateModal"> 템플릿 생성</button>
<button class="btn btn--ghost" @click="openGamePickerModal('game-admin')">템플릿 선택</button>
<div v-if="selectedGame?.game" class="adminSelectionCard">
<div class="adminSelectionCard__label">선택한 게임</div>
<div class="adminSelectionCard__label">선택한 템플릿</div>
<div class="adminSelectionCard__title">{{ selectedGame.game.name }}</div>
<div class="adminSelectionCard__meta">{{ selectedGame.game.id }}</div>
</div>
<div v-if="selectedGameId && !hasSelectedGame && !isGameLoading" class="hint hint--tight">선택된 게임 ID: {{ selectedGameId }}</div>
<div v-if="selectedGameId && !hasSelectedGame && !isGameLoading" class="hint hint--tight">선택된 템플릿 ID: {{ selectedGameId }}</div>
</div>
</section>
@@ -2277,14 +2277,14 @@ function userAvatarFallback(user) {
<input
v-model="adminTierListQuery"
class="input"
placeholder="제목, 작성자, 게임 이름 검색"
placeholder="제목, 작성자, 주제 이름 검색"
@keydown.enter.prevent="submitAdminTierListSearch"
/>
<button class="btn btn--ghost" @click="submitAdminTierListSearch">검색</button>
</div>
<button class="btn btn--ghost" @click="openGamePickerModal('tierlists-filter')">게임 선택</button>
<button class="btn btn--ghost" @click="openGamePickerModal('tierlists-filter')">주제 선택</button>
<div v-if="adminTierListGameId" class="adminSelectionCard">
<div class="adminSelectionCard__label">필터된 게임</div>
<div class="adminSelectionCard__label">필터된 주제</div>
<div class="adminSelectionCard__title">{{ games.find((game) => game.id === adminTierListGameId)?.name || adminTierListGameId }}</div>
<div class="adminSelectionCard__meta">{{ adminTierListGameId }}</div>
<button class="btn btn--ghost btn--small" @click="setAdminTierListGameId('')">필터 해제</button>