|
|
|
|
@@ -424,11 +424,11 @@ watch(
|
|
|
|
|
(name) => {
|
|
|
|
|
activeTab.value = tabFromAdminRoute(name)
|
|
|
|
|
if (name === 'adminGames') {
|
|
|
|
|
const nextGameId = typeof route.query.gameId === 'string' ? route.query.gameId : ''
|
|
|
|
|
if (nextGameId && nextGameId !== selectedTemplateId.value) {
|
|
|
|
|
selectedTemplateId.value = nextGameId
|
|
|
|
|
const nextTopicId = typeof route.query.topicId === 'string' ? route.query.topicId : ''
|
|
|
|
|
if (nextTopicId && nextTopicId !== selectedTemplateId.value) {
|
|
|
|
|
selectedTemplateId.value = nextTopicId
|
|
|
|
|
queueMicrotask(() => {
|
|
|
|
|
if (selectedTemplateId.value === nextGameId) void loadTemplate()
|
|
|
|
|
if (selectedTemplateId.value === nextTopicId) void loadTemplate()
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
@@ -436,8 +436,8 @@ watch(
|
|
|
|
|
if (name === 'adminTierlists') {
|
|
|
|
|
const nextMode = route.query.mode === 'all' ? 'all' : 'requests'
|
|
|
|
|
if (tierlistsMode.value !== nextMode) tierlistsMode.value = nextMode
|
|
|
|
|
const nextTierListGameId = typeof route.query.gameId === 'string' ? route.query.gameId : ''
|
|
|
|
|
if (adminTierListGameId.value !== nextTierListGameId) adminTierListGameId.value = nextTierListGameId
|
|
|
|
|
const nextTierListTopicId = typeof route.query.topicId === 'string' ? route.query.topicId : ''
|
|
|
|
|
if (adminTierListGameId.value !== nextTierListTopicId) adminTierListGameId.value = nextTierListTopicId
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{ immediate: true }
|
|
|
|
|
@@ -447,7 +447,7 @@ watch(
|
|
|
|
|
() => selectedTemplateId.value,
|
|
|
|
|
(templateId) => {
|
|
|
|
|
if (route.name !== 'adminGames') return
|
|
|
|
|
syncAdminRouteQuery({ gameId: templateId || undefined })
|
|
|
|
|
syncAdminRouteQuery({ topicId: templateId || undefined })
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@@ -465,16 +465,16 @@ watch(
|
|
|
|
|
if (route.name !== 'adminTierlists') return
|
|
|
|
|
syncAdminRouteQuery({
|
|
|
|
|
mode: mode === 'all' ? 'all' : undefined,
|
|
|
|
|
gameId: mode === 'all' && adminTierListGameId.value ? adminTierListGameId.value : undefined,
|
|
|
|
|
topicId: mode === 'all' && adminTierListGameId.value ? adminTierListGameId.value : undefined,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
watch(
|
|
|
|
|
() => adminTierListGameId.value,
|
|
|
|
|
(gameId) => {
|
|
|
|
|
(topicId) => {
|
|
|
|
|
if (route.name !== 'adminTierlists' || tierlistsMode.value !== 'all') return
|
|
|
|
|
syncAdminRouteQuery({ gameId: gameId || undefined })
|
|
|
|
|
syncAdminRouteQuery({ topicId: topicId || undefined })
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
@@ -733,7 +733,7 @@ function setTab(tab) {
|
|
|
|
|
if (nextRouteName && route.name !== nextRouteName) {
|
|
|
|
|
const nextQuery =
|
|
|
|
|
tab === 'game-admin'
|
|
|
|
|
? { gameId: selectedTemplateId.value || undefined }
|
|
|
|
|
? { topicId: selectedTemplateId.value || undefined }
|
|
|
|
|
: tab === 'tierlists' && tierlistsMode.value === 'all'
|
|
|
|
|
? { mode: 'all' }
|
|
|
|
|
: {}
|
|
|
|
|
@@ -758,10 +758,10 @@ function setTierlistsMode(mode) {
|
|
|
|
|
|
|
|
|
|
function openTemplateCreateModal() {
|
|
|
|
|
resetMessages()
|
|
|
|
|
if (activeTemplateRequest.value?.type === 'create' && !activeTemplateRequest.value?.targetGameId) {
|
|
|
|
|
newTemplateId.value = activeTemplateRequest.value?.draftGameId || ''
|
|
|
|
|
newTemplateName.value = activeTemplateRequest.value?.draftGameName || ''
|
|
|
|
|
newTemplateIsPublic.value = !!activeTemplateRequest.value?.draftGameIsPublic
|
|
|
|
|
if (activeTemplateRequest.value?.type === 'create' && !activeTemplateRequest.value?.targetTopicId) {
|
|
|
|
|
newTemplateId.value = activeTemplateRequest.value?.draftTopicId || ''
|
|
|
|
|
newTemplateName.value = activeTemplateRequest.value?.draftTopicName || ''
|
|
|
|
|
newTemplateIsPublic.value = !!activeTemplateRequest.value?.draftTopicIsPublic
|
|
|
|
|
} else {
|
|
|
|
|
newTemplateId.value = ''
|
|
|
|
|
newTemplateName.value = ''
|
|
|
|
|
@@ -822,7 +822,7 @@ async function refreshAdminTierLists() {
|
|
|
|
|
try {
|
|
|
|
|
const data = await api.listAdminTierLists({
|
|
|
|
|
q: adminTierListQuery.value,
|
|
|
|
|
gameId: adminTierListGameId.value,
|
|
|
|
|
topicId: adminTierListGameId.value,
|
|
|
|
|
page: adminTierListPage.value,
|
|
|
|
|
limit: adminTierListLimit.value,
|
|
|
|
|
})
|
|
|
|
|
@@ -839,7 +839,7 @@ async function refreshAdminTierLists() {
|
|
|
|
|
async function refreshAdminTierListStats() {
|
|
|
|
|
if (!auth.user?.isAdmin) return
|
|
|
|
|
try {
|
|
|
|
|
const data = await api.getAdminTierListStats({ q: adminTierListQuery.value, gameId: adminTierListGameId.value })
|
|
|
|
|
const data = await api.getAdminTierListStats({ q: adminTierListQuery.value, topicId: adminTierListGameId.value })
|
|
|
|
|
adminTierListStats.value = {
|
|
|
|
|
total: data.total || 0,
|
|
|
|
|
publicCount: data.publicCount || 0,
|
|
|
|
|
@@ -857,7 +857,7 @@ async function refreshSelectedTemplateTierListStats(templateId = '') {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
const data = await api.getAdminTierListStats({ gameId: templateId })
|
|
|
|
|
const data = await api.getAdminTierListStats({ topicId: templateId })
|
|
|
|
|
selectedTemplateTierListStats.value = {
|
|
|
|
|
total: data.total || 0,
|
|
|
|
|
publicCount: data.publicCount || 0,
|
|
|
|
|
@@ -874,15 +874,15 @@ async function refreshTemplateRequests() {
|
|
|
|
|
const data = await api.listAdminTemplateRequests()
|
|
|
|
|
templateRequests.value = (data.requests || []).map((request) => ({
|
|
|
|
|
...request,
|
|
|
|
|
draftGameId:
|
|
|
|
|
draftTopicId:
|
|
|
|
|
request.type === 'create'
|
|
|
|
|
? ('tmpl-' + String(request.id || 'request').replace(/[^a-zA-Z0-9]+/g, '').slice(0, 12).toLowerCase())
|
|
|
|
|
: request.targetGameId || request.sourceGameId || '',
|
|
|
|
|
draftGameName:
|
|
|
|
|
: request.targetTopicId || request.sourceTopicId || '',
|
|
|
|
|
draftTopicName:
|
|
|
|
|
request.type === 'create'
|
|
|
|
|
? `${request.sourceTierListTitle || request.sourceGameName || '새 템플릿'}`
|
|
|
|
|
: request.targetGameName || request.sourceGameName || '',
|
|
|
|
|
draftGameIsPublic: false,
|
|
|
|
|
? `${request.sourceTierListTitle || request.sourceTopicName || '새 템플릿'}`
|
|
|
|
|
: request.targetTopicName || request.sourceTopicName || '',
|
|
|
|
|
draftTopicIsPublic: false,
|
|
|
|
|
}))
|
|
|
|
|
} catch (e) {
|
|
|
|
|
error.value = '템플릿 요청 목록을 불러오지 못했어요.'
|
|
|
|
|
@@ -1306,8 +1306,8 @@ function submitAdminTierListSearch() {
|
|
|
|
|
refreshAdminTierLists()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function setAdminTierListGameId(gameId) {
|
|
|
|
|
adminTierListGameId.value = gameId || ''
|
|
|
|
|
function setAdminTierListGameId(topicId) {
|
|
|
|
|
adminTierListGameId.value = topicId || ''
|
|
|
|
|
adminTierListPage.value = 1
|
|
|
|
|
refreshAdminTierLists()
|
|
|
|
|
}
|
|
|
|
|
@@ -1551,8 +1551,8 @@ function closePreviewModal() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function previewTierListUrl(tierList) {
|
|
|
|
|
if (!tierList?.gameId || !tierList?.id) return ''
|
|
|
|
|
return editorPath(tierList.gameId, tierList.id, { preview: true })
|
|
|
|
|
if (!tierList?.topicId || !tierList?.id) return ''
|
|
|
|
|
return editorPath(tierList.topicId, tierList.id, { preview: true })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function openTierListImportModal(tierList, items) {
|
|
|
|
|
@@ -1567,9 +1567,9 @@ function openTierListImportModal(tierList, items) {
|
|
|
|
|
importModalItems.value = nextItems
|
|
|
|
|
importModalMode.value = 'existing'
|
|
|
|
|
importModalTargetTemplateId.value = ''
|
|
|
|
|
importModalNewTemplateId.value = tierList.gameId === 'freeform' ? '' : `${tierList.gameId}-copy`
|
|
|
|
|
importModalNewTemplateId.value = tierList.topicId === 'freeform' ? '' : `${tierList.topicId}-copy`
|
|
|
|
|
importModalNewTemplateName.value =
|
|
|
|
|
tierList.gameId === 'freeform' ? `${tierList.title} 템플릿` : `${tierList.gameName || tierList.gameId} 파생 템플릿`
|
|
|
|
|
tierList.topicId === 'freeform' ? `${tierList.title} 템플릿` : `${tierList.topicName || tierList.topicId} 파생 템플릿`
|
|
|
|
|
importModalOpen.value = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1597,26 +1597,26 @@ async function confirmTierListImport() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const data = await api.promoteAdminTierListItems(tierList.id, {
|
|
|
|
|
gameId: importModalTargetTemplateId.value,
|
|
|
|
|
topicId: importModalTargetTemplateId.value,
|
|
|
|
|
itemIds,
|
|
|
|
|
})
|
|
|
|
|
if (selectedTemplateId.value === importModalTargetTemplateId.value) await loadTemplate()
|
|
|
|
|
success.value = `${data.items?.length || 0}개의 아이템을 기존 템플릿에 추가했어요.`
|
|
|
|
|
} else {
|
|
|
|
|
const nextGameId = (importModalNewTemplateId.value || '').trim()
|
|
|
|
|
const nextGameName = (importModalNewTemplateName.value || '').trim()
|
|
|
|
|
if (!nextGameId || !nextGameName) {
|
|
|
|
|
const nextTopicId = (importModalNewTemplateId.value || '').trim()
|
|
|
|
|
const nextTopicName = (importModalNewTemplateName.value || '').trim()
|
|
|
|
|
if (!nextTopicId || !nextTopicName) {
|
|
|
|
|
error.value = '새 템플릿 ID와 이름을 모두 입력해주세요.'
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const data = await api.createAdminTemplateFromTierList(tierList.id, {
|
|
|
|
|
gameId: nextGameId,
|
|
|
|
|
name: nextGameName,
|
|
|
|
|
topicId: nextTopicId,
|
|
|
|
|
name: nextTopicName,
|
|
|
|
|
itemIds,
|
|
|
|
|
})
|
|
|
|
|
await refreshTemplates()
|
|
|
|
|
success.value = `"${data.template?.name || nextGameName}" 템플릿을 생성했어요.`
|
|
|
|
|
success.value = `"${data.template?.name || nextTopicName}" 템플릿을 생성했어요.`
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
closeTierListImportModal()
|
|
|
|
|
@@ -1631,12 +1631,12 @@ function templateRequestTypeLabel(request) {
|
|
|
|
|
|
|
|
|
|
function templateRequestTargetLabel(request) {
|
|
|
|
|
if (request.type === 'create') {
|
|
|
|
|
if (request.targetGameName || request.targetGameId) {
|
|
|
|
|
return `연결된 템플릿 · ${request.targetGameName || request.targetGameId}`
|
|
|
|
|
if (request.targetTopicName || request.targetTopicId) {
|
|
|
|
|
return `연결된 템플릿 · ${request.targetTopicName || request.targetTopicId}`
|
|
|
|
|
}
|
|
|
|
|
return '연결된 템플릿 없음'
|
|
|
|
|
}
|
|
|
|
|
return request.targetGameName || request.targetGameId || request.sourceGameName
|
|
|
|
|
return request.targetTopicName || request.targetTopicId || request.sourceTopicName
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const displayThumbnailUrl = computed(() => {
|
|
|
|
|
@@ -2095,7 +2095,7 @@ function userAvatarFallback(user) {
|
|
|
|
|
<div class="modalCard" role="dialog" aria-modal="true">
|
|
|
|
|
<div class="modalCard__title">티어표 관리</div>
|
|
|
|
|
<div class="modalCard__desc">
|
|
|
|
|
{{ modalTargetAdminTierList ? `${modalTargetAdminTierList.gameName || modalTargetAdminTierList.gameId} · ${tierListAuthorDisplayName(modalTargetAdminTierList)}` : '' }}
|
|
|
|
|
{{ modalTargetAdminTierList ? `${modalTargetAdminTierList.topicName || modalTargetAdminTierList.topicId} · ${tierListAuthorDisplayName(modalTargetAdminTierList)}` : '' }}
|
|
|
|
|
</div>
|
|
|
|
|
<div class="modalCard__form">
|
|
|
|
|
<label class="field">
|
|
|
|
|
|