릴리스: v1.3.49 템플릿 요청 저장 흐름과 관리자 미리보기 정리
This commit is contained in:
@@ -1381,7 +1381,14 @@ function previewRequestGroupCellItems(preview, group, columnIndex) {
|
||||
}
|
||||
|
||||
function previewRequestPoolItems(preview) {
|
||||
const groupedIds = new Set((preview?.snapshotGroups || []).flatMap((group) => group.itemIds || []))
|
||||
const groupedIds = new Set(
|
||||
(preview?.snapshotGroups || []).flatMap((group) => {
|
||||
if (Array.isArray(group?.cells) && group.cells.length) {
|
||||
return group.cells.flatMap((cell) => (Array.isArray(cell) ? cell : []))
|
||||
}
|
||||
return group.itemIds || []
|
||||
})
|
||||
)
|
||||
return (preview?.snapshotItems || []).filter((item) => !groupedIds.has(item.id))
|
||||
}
|
||||
|
||||
@@ -2278,24 +2285,21 @@ async function saveFeaturedOrder() {
|
||||
</div>
|
||||
|
||||
<div v-if="previewTierList?.requestPreview" class="requestPreview">
|
||||
<div class="requestPreview__frame">
|
||||
<div class="requestPreview__header">
|
||||
<div class="requestPreview__heroTitle">{{ previewTierList.title || '티어표 미리보기' }}</div>
|
||||
<div v-if="previewTierList.description" class="requestPreview__desc">{{ previewTierList.description }}</div>
|
||||
<div class="requestPreview__meta">
|
||||
{{ previewRequestHasColumns(previewTierList) ? (previewRequestColumns(previewTierList).length + '열 구성') : '단일 열 구성' }} ·
|
||||
{{ previewTierList.snapshotGroups?.length || 0 }}개 행 ·
|
||||
{{ previewTierList.snapshotItems?.length || 0 }}개 아이템
|
||||
</div>
|
||||
<div class="requestPreview__sheet">
|
||||
<div class="requestPreview__title">{{ previewTierList.title || '티어표 미리보기' }}</div>
|
||||
<div v-if="previewTierList.description" class="requestPreview__description">{{ previewTierList.description }}</div>
|
||||
<div class="requestPreview__meta">
|
||||
{{ previewRequestHasColumns(previewTierList) ? (previewRequestColumns(previewTierList).length + '열 구성') : '단일 열 구성' }} ·
|
||||
{{ previewTierList.snapshotGroups?.length || 0 }}개 행 ·
|
||||
{{ previewTierList.snapshotItems?.length || 0 }}개 아이템
|
||||
</div>
|
||||
<div class="requestPreview__board requestPreview__board--full">
|
||||
<div v-if="previewRequestHasColumns(previewTierList)" class="requestPreview__boardHead">
|
||||
<div class="requestPreview__rowLabel requestPreview__rowLabel--head">행</div>
|
||||
<div class="requestPreview__columnLabels" :style="previewRequestGridStyle(previewTierList)">
|
||||
<div v-if="previewRequestHasColumns(previewTierList)" class="requestPreview__columns">
|
||||
<div class="requestPreview__columnsSpacer" aria-hidden="true"></div>
|
||||
<div class="requestPreview__columnsGrid" :style="previewRequestGridStyle(previewTierList)">
|
||||
<div
|
||||
v-for="(column, columnIndex) in previewRequestColumns(previewTierList)"
|
||||
:key="column.id"
|
||||
class="requestPreview__columnLabel"
|
||||
class="requestPreview__columnHeader"
|
||||
>
|
||||
{{ column.name || ('열 ' + (columnIndex + 1)) }}
|
||||
</div>
|
||||
@@ -2303,38 +2307,37 @@ async function saveFeaturedOrder() {
|
||||
</div>
|
||||
<div class="requestPreview__rows">
|
||||
<div v-for="group in previewTierList.snapshotGroups" :key="group.id" class="requestPreview__row">
|
||||
<div class="requestPreview__rowLabel">{{ group.name }}</div>
|
||||
<div class="requestPreview__cells" :style="previewRequestGridStyle(previewTierList)">
|
||||
<div class="requestPreview__label">{{ group.name }}</div>
|
||||
<div class="requestPreview__dropGrid" :style="previewRequestGridStyle(previewTierList)">
|
||||
<div
|
||||
v-for="(column, columnIndex) in previewRequestColumns(previewTierList)"
|
||||
:key="group.id + '-' + column.id"
|
||||
class="requestPreview__cell"
|
||||
class="requestPreview__dropColumn"
|
||||
>
|
||||
<div class="requestPreview__rowItems">
|
||||
<div class="requestPreview__drop">
|
||||
<div
|
||||
v-for="item in previewRequestGroupCellItems(previewTierList, group, columnIndex)"
|
||||
:key="item.id"
|
||||
class="requestPreview__item"
|
||||
>
|
||||
<img class="requestPreview__itemThumb" :src="toApiUrl(item.src)" :alt="item.label" />
|
||||
<div v-if="previewTierList.snapshotShowCharacterNames" class="requestPreview__itemLabel">{{ item.label }}</div>
|
||||
<img class="thumb requestPreview__itemThumb" :src="toApiUrl(item.src)" :alt="item.label" />
|
||||
<div v-if="previewTierList.snapshotShowCharacterNames" class="itemNameOverlay requestPreview__itemLabel">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="previewRequestPoolItems(previewTierList).length" class="requestPreview__pool">
|
||||
<div class="requestPreview__poolLabel">남은 아이템</div>
|
||||
<div class="requestPreview__rowItems requestPreview__rowItems--pool">
|
||||
<div class="requestPreview__poolTitle">남은 아이템</div>
|
||||
<div class="requestPreview__poolGrid">
|
||||
<div
|
||||
v-for="item in previewRequestPoolItems(previewTierList)"
|
||||
:key="item.id"
|
||||
class="requestPreview__item requestPreview__item--muted"
|
||||
class="requestPreview__poolItem requestPreview__item requestPreview__item--muted"
|
||||
>
|
||||
<img class="requestPreview__itemThumb" :src="toApiUrl(item.src)" :alt="item.label" />
|
||||
<div v-if="previewTierList.snapshotShowCharacterNames" class="requestPreview__itemLabel">{{ item.label }}</div>
|
||||
<img class="thumb requestPreview__itemThumb" :src="toApiUrl(item.src)" :alt="item.label" />
|
||||
<div v-if="previewTierList.snapshotShowCharacterNames" class="itemNameOverlay requestPreview__itemLabel">{{ item.label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -3887,9 +3890,14 @@ async function saveFeaturedOrder() {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
align-self: start;
|
||||
align-content: start;
|
||||
}
|
||||
.templateRequestCard__preview {
|
||||
align-self: start;
|
||||
display: block;
|
||||
width: 100%;
|
||||
line-height: 0;
|
||||
vertical-align: top;
|
||||
}
|
||||
.templateRequestCard__thumbMeta {
|
||||
display: grid;
|
||||
@@ -3916,97 +3924,103 @@ async function saveFeaturedOrder() {
|
||||
}
|
||||
.requestPreview {
|
||||
display: grid;
|
||||
gap: 18px;
|
||||
}
|
||||
.requestPreview__frame {
|
||||
.requestPreview__sheet {
|
||||
display: grid;
|
||||
gap: 26px;
|
||||
gap: 16px;
|
||||
width: 100%;
|
||||
max-width: 1280px;
|
||||
margin: 0 auto;
|
||||
padding: 28px;
|
||||
border-radius: 24px;
|
||||
border: 1px solid var(--theme-border);
|
||||
background: color-mix(in srgb, var(--theme-main-bg) 92%, transparent);
|
||||
max-height: min(78vh, 980px);
|
||||
overflow: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
.requestPreview__header {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.requestPreview__heroTitle {
|
||||
font-size: clamp(30px, 3vw, 48px);
|
||||
line-height: 1.08;
|
||||
.requestPreview__title {
|
||||
font-size: 28px;
|
||||
font-weight: 900;
|
||||
letter-spacing: -0.04em;
|
||||
letter-spacing: -0.03em;
|
||||
}
|
||||
.requestPreview__description {
|
||||
margin-top: -8px;
|
||||
font-size: 14px;
|
||||
line-height: 1.6;
|
||||
color: var(--theme-text-muted);
|
||||
}
|
||||
.requestPreview__meta {
|
||||
color: var(--theme-text-soft);
|
||||
font-size: 13px;
|
||||
}
|
||||
.requestPreview__desc {
|
||||
color: var(--theme-text-muted);
|
||||
line-height: 1.7;
|
||||
white-space: pre-line;
|
||||
font-size: 15px;
|
||||
}
|
||||
.requestPreview__board,
|
||||
.requestPreview__pool {
|
||||
.requestPreview__columns {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
grid-template-columns: 132px 1fr;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.requestPreview__boardHead,
|
||||
.requestPreview__row {
|
||||
display: grid;
|
||||
grid-template-columns: 120px minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
align-items: start;
|
||||
}
|
||||
.requestPreview__rowLabel,
|
||||
.requestPreview__poolLabel,
|
||||
.requestPreview__columnLabel {
|
||||
font-size: 15px;
|
||||
font-weight: 900;
|
||||
color: var(--theme-text-strong);
|
||||
}
|
||||
.requestPreview__rowLabel--head {
|
||||
color: var(--theme-text-faint);
|
||||
}
|
||||
.requestPreview__columnLabels,
|
||||
.requestPreview__cells {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
.requestPreview__columnLabel,
|
||||
.requestPreview__cell {
|
||||
.requestPreview__columnsSpacer {
|
||||
min-width: 0;
|
||||
}
|
||||
.requestPreview__columnLabel {
|
||||
padding: 8px 4px;
|
||||
text-align: center;
|
||||
}
|
||||
.requestPreview__cell {
|
||||
min-height: 134px;
|
||||
padding: 14px;
|
||||
border-radius: 18px;
|
||||
border: 1px solid var(--theme-border);
|
||||
background: var(--theme-surface-soft);
|
||||
}
|
||||
.requestPreview__rowItems {
|
||||
.requestPreview__columnsGrid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
|
||||
gap: 12px;
|
||||
gap: 10px;
|
||||
}
|
||||
.requestPreview__rowItems--pool {
|
||||
grid-template-columns: repeat(auto-fill, minmax(84px, 1fr));
|
||||
.requestPreview__columnHeader {
|
||||
min-height: 20px;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
text-align: center;
|
||||
opacity: 0.72;
|
||||
}
|
||||
.requestPreview__rows {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.requestPreview__row {
|
||||
display: grid;
|
||||
grid-template-columns: 132px 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
.requestPreview__label {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
padding: 10px 12px;
|
||||
text-align: center;
|
||||
font-weight: 900;
|
||||
border-radius: 14px;
|
||||
background: var(--theme-surface-soft-2);
|
||||
border: 1px solid var(--theme-border-strong);
|
||||
}
|
||||
.requestPreview__dropGrid {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
}
|
||||
.requestPreview__dropColumn {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
.requestPreview__drop {
|
||||
border-radius: 14px;
|
||||
background: var(--theme-pill-bg);
|
||||
border: 1px solid var(--theme-border);
|
||||
min-height: calc(var(--thumb-size, 80px) + 24px);
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-content: flex-start;
|
||||
}
|
||||
.requestPreview__item {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 16px;
|
||||
border: 1px solid rgba(255, 255, 255, 0.12);
|
||||
background: var(--theme-surface-soft);
|
||||
min-height: 84px;
|
||||
}
|
||||
.requestPreview__item--muted {
|
||||
opacity: 0.52;
|
||||
filter: grayscale(0.2) brightness(0.78);
|
||||
filter: grayscale(0.22) brightness(0.78);
|
||||
}
|
||||
.requestPreview__itemThumb {
|
||||
width: 100%;
|
||||
@@ -4027,6 +4041,24 @@ async function saveFeaturedOrder() {
|
||||
text-align: center;
|
||||
line-height: 1.3;
|
||||
}
|
||||
.requestPreview__pool {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
.requestPreview__poolTitle {
|
||||
font-weight: 900;
|
||||
opacity: 0.82;
|
||||
}
|
||||
.requestPreview__poolGrid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
}
|
||||
.requestPreview__poolItem {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
}
|
||||
.tierAdminList {
|
||||
margin-top: 14px;
|
||||
display: grid;
|
||||
@@ -4051,11 +4083,13 @@ async function saveFeaturedOrder() {
|
||||
align-self: start;
|
||||
display: block;
|
||||
width: 100%;
|
||||
line-height: 0;
|
||||
}
|
||||
.tierAdminCard__thumb {
|
||||
width: 100%;
|
||||
aspect-ratio: 16 / 9;
|
||||
object-fit: cover;
|
||||
object-position: top center;
|
||||
display: block;
|
||||
border-radius: 14px;
|
||||
background: var(--theme-surface-soft);
|
||||
@@ -4200,6 +4234,9 @@ async function saveFeaturedOrder() {
|
||||
}
|
||||
.modalCard--preview {
|
||||
width: min(1200px, 100%);
|
||||
max-height: calc(100dvh - 40px);
|
||||
overflow: auto;
|
||||
overscroll-behavior: contain;
|
||||
}
|
||||
.modalCard__titleRow {
|
||||
display: flex;
|
||||
|
||||
@@ -34,6 +34,7 @@ const pool = ref([])
|
||||
const itemsById = ref({})
|
||||
|
||||
const title = ref('')
|
||||
const persistedTierListId = ref('')
|
||||
const thumbnailSrc = ref('')
|
||||
const pendingThumbnailFile = ref(null)
|
||||
const thumbnailPreviewUrl = ref('')
|
||||
@@ -48,7 +49,6 @@ const isTemplateRequestModalOpen = ref(false)
|
||||
const isTemplateUpdateModalOpen = ref(false)
|
||||
const templateRequestDraftTitle = ref('')
|
||||
const templateRequestDraftDescription = ref('')
|
||||
const templateRequestSaveToMyTierList = ref(true)
|
||||
const isDeleteModalOpen = ref(false)
|
||||
const isGroupDeleteModalOpen = ref(false)
|
||||
const isColumnDeleteModalOpen = ref(false)
|
||||
@@ -94,10 +94,13 @@ const effectiveAuthorName = computed(() => {
|
||||
if (currentEmail) return currentEmail.split('@')[0] || currentEmail
|
||||
return (authorAccountName.value || '').trim() || 'unknown'
|
||||
})
|
||||
const autoGeneratedTitle = ref(createAutoTierListTitle())
|
||||
const effectiveTitle = computed(() => {
|
||||
const customTitle = (title.value || '').trim()
|
||||
if (customTitle) return customTitle
|
||||
return (gameName.value || gameId.value || 'Tier Maker').trim()
|
||||
if (persistedTierListId.value) return persistedTierListId.value
|
||||
if (tierListId.value && tierListId.value !== 'new') return tierListId.value
|
||||
return autoGeneratedTitle.value
|
||||
})
|
||||
const displayThumbnailUrl = computed(() => thumbnailPreviewUrl.value || (thumbnailSrc.value ? resolveItemSrc({ src: thumbnailSrc.value }) : ''))
|
||||
const untitledWarning = computed(
|
||||
@@ -120,11 +123,12 @@ const customItems = computed(() =>
|
||||
.filter((item) => item?.origin === 'custom')
|
||||
.sort((a, b) => (a.label || '').localeCompare(b.label || '', 'ko'))
|
||||
)
|
||||
const hasSavedTierList = computed(() => !!(persistedTierListId.value || (tierListId.value && tierListId.value !== 'new')))
|
||||
const canRequestTemplateCreate = computed(
|
||||
() => canEdit.value && !isNewTierList.value && gameId.value === 'freeform' && customItems.value.length > 0
|
||||
() => canEdit.value && hasSavedTierList.value && gameId.value === 'freeform' && customItems.value.length > 0
|
||||
)
|
||||
const canRequestTemplateUpdate = computed(
|
||||
() => canEdit.value && !isNewTierList.value && gameId.value !== 'freeform' && customItems.value.length > 0
|
||||
() => canEdit.value && hasSavedTierList.value && gameId.value !== 'freeform' && customItems.value.length > 0
|
||||
)
|
||||
const canSubmitTemplateCreateRequest = computed(() => !!templateRequestDraftTitle.value.trim() && !!templateRequestDraftDescription.value.trim())
|
||||
const canSubmitTemplateUpdateRequest = computed(() => !!templateRequestDraftTitle.value.trim() && !!templateRequestDraftDescription.value.trim())
|
||||
@@ -136,6 +140,12 @@ watch(error, (message) => {
|
||||
error.value = ''
|
||||
})
|
||||
|
||||
function createAutoTierListTitle() {
|
||||
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
|
||||
const pick = (size) => Array.from({ length: size }, () => chars[Math.floor(Math.random() * chars.length)]).join('')
|
||||
return pick(10) + '-' + pick(10)
|
||||
}
|
||||
|
||||
function formatTitleDate(ts) {
|
||||
const date = new Date(ts)
|
||||
const year = date.getFullYear()
|
||||
@@ -652,9 +662,12 @@ function buildPayload(existingId) {
|
||||
async function persistTierList({ showModal = false } = {}) {
|
||||
await uploadPendingCustomItems()
|
||||
await uploadPendingThumbnail()
|
||||
const payload = buildPayload(tierListId.value && tierListId.value !== 'new' ? tierListId.value : null)
|
||||
const currentTierListId = persistedTierListId.value || (tierListId.value && tierListId.value !== 'new' ? tierListId.value : '')
|
||||
const payload = buildPayload(currentTierListId || null)
|
||||
const res = await api.saveTierList(payload)
|
||||
const savedTierListId = res.tierList?.id || tierListId.value
|
||||
const savedTierListId = res.tierList?.id || currentTierListId || tierListId.value
|
||||
persistedTierListId.value = savedTierListId || ''
|
||||
title.value = res.tierList?.title || payload.title
|
||||
if (tierListId.value === 'new' && res.tierList?.id) {
|
||||
await router.replace(`/editor/${gameId.value}/${res.tierList.id}`)
|
||||
}
|
||||
@@ -686,7 +699,6 @@ function closeSaveModal() {
|
||||
function resetTemplateRequestDrafts() {
|
||||
templateRequestDraftTitle.value = (title.value || '').trim()
|
||||
templateRequestDraftDescription.value = (description.value || '').trim()
|
||||
templateRequestSaveToMyTierList.value = true
|
||||
}
|
||||
|
||||
function openTemplateRequestModal() {
|
||||
@@ -762,55 +774,39 @@ async function toggleFavorite() {
|
||||
}
|
||||
|
||||
async function requestTemplate(type) {
|
||||
const shouldSaveToMyTierList = !!templateRequestSaveToMyTierList.value
|
||||
try {
|
||||
isRequestingTemplate.value = true
|
||||
await uploadPendingCustomItems()
|
||||
const uploadedThumbnailSrc = await uploadPendingThumbnail()
|
||||
const response = await api.requestTierListTemplate({
|
||||
title.value = templateRequestDraftTitle.value.trim()
|
||||
description.value = templateRequestDraftDescription.value.trim()
|
||||
const saved = await persistTierList({ showModal: false })
|
||||
const sourceId = saved.savedTierListId || persistedTierListId.value || ''
|
||||
if (!sourceId) throw new Error('save_required')
|
||||
|
||||
await api.requestTierListTemplate({
|
||||
type,
|
||||
sourceTierListId: tierListId.value !== 'new' ? tierListId.value : '',
|
||||
sourceTierListId: sourceId,
|
||||
gameId: gameId.value,
|
||||
requestTitle: templateRequestDraftTitle.value.trim(),
|
||||
requestDescription: templateRequestDraftDescription.value.trim(),
|
||||
thumbnailSrc: uploadedThumbnailSrc || thumbnailSrc.value || '',
|
||||
thumbnailSrc: saved.tierList?.thumbnailSrc || thumbnailSrc.value || '',
|
||||
isPublic: !!isPublic.value,
|
||||
showCharacterNames: !!showCharacterNames.value,
|
||||
saveToMyTierList: shouldSaveToMyTierList,
|
||||
groups: buildGroupPayload(),
|
||||
boardItems: Object.values(itemsById.value),
|
||||
})
|
||||
|
||||
const savedTierList = response?.savedTierList
|
||||
if (savedTierList) {
|
||||
title.value = savedTierList.title || title.value
|
||||
description.value = savedTierList.description || ''
|
||||
updatedAt.value = Number(savedTierList.updatedAt || Date.now())
|
||||
authorName.value = savedTierList.authorName || effectiveAuthorName.value
|
||||
authorAccountName.value = savedTierList.authorAccountName || authorAccountName.value
|
||||
favoriteCount.value = Number(savedTierList.favoriteCount || favoriteCount.value || 0)
|
||||
isFavorited.value = !!savedTierList.isFavorited
|
||||
if (tierListId.value === 'new' && savedTierList.id) {
|
||||
await router.replace(`/editor/${gameId.value}/${savedTierList.id}`)
|
||||
}
|
||||
}
|
||||
|
||||
if (type === 'create') closeTemplateRequestModal()
|
||||
if (type === 'update') closeTemplateUpdateModal()
|
||||
toast.success(
|
||||
type === 'create'
|
||||
? shouldSaveToMyTierList
|
||||
? '템플릿 등록 요청과 내 티어표 저장을 함께 완료했어요.'
|
||||
: '템플릿 등록 요청을 보냈어요.'
|
||||
: shouldSaveToMyTierList
|
||||
? '템플릿 업데이트 요청과 내 티어표 저장을 함께 완료했어요.'
|
||||
: '템플릿 업데이트 요청을 보냈어요.'
|
||||
)
|
||||
toast.success(type === 'create' ? '템플릿 등록 요청을 보냈어요.' : '템플릿 업데이트 요청을 보냈어요.')
|
||||
} catch (e) {
|
||||
if (e?.message === 'custom_upload_failed') {
|
||||
toast.error('커스텀 이미지 이름이 너무 길거나 업로드 조건에 맞지 않아 요청 전에 저장하지 못했어요. 아이템 이름을 60자 이하로 줄인 뒤 다시 시도해주세요.')
|
||||
return
|
||||
}
|
||||
if (e?.message === 'save_required') {
|
||||
toast.error('먼저 현재 티어표를 저장한 뒤 다시 요청해주세요.')
|
||||
return
|
||||
}
|
||||
if (e?.status === 409) {
|
||||
toast.error('이미 처리 대기 중인 같은 요청이 있어요.')
|
||||
return
|
||||
@@ -819,12 +815,12 @@ async function requestTemplate(type) {
|
||||
toast.error('먼저 커스텀 아이템을 추가한 뒤 요청해주세요.')
|
||||
return
|
||||
}
|
||||
if (e?.status === 400 && e?.data?.error === 'bad_request') {
|
||||
toast.error('요청 제목, 설명, 아이템 이름 중 길이 제한을 넘긴 값이 없는지 확인해주세요.')
|
||||
if (e?.status === 400 && e?.data?.error === 'source_tierlist_required') {
|
||||
toast.error('저장된 티어표에서만 템플릿 요청을 보낼 수 있어요.')
|
||||
return
|
||||
}
|
||||
if (e?.status === 500 && shouldSaveToMyTierList) {
|
||||
toast.error('템플릿 요청 중 내 티어리스트 저장에 실패했어요. 잠시 후 다시 시도해주세요.')
|
||||
if (e?.status === 400 && e?.data?.error === 'bad_request') {
|
||||
toast.error('요청 제목, 설명, 아이템 이름 중 길이 제한을 넘긴 값이 없는지 확인해주세요.')
|
||||
return
|
||||
}
|
||||
toast.error(type === 'create' ? '템플릿 등록 요청에 실패했어요.' : '템플릿 업데이트 요청에 실패했어요.')
|
||||
@@ -866,6 +862,7 @@ onMounted(() => {
|
||||
const res = await api.getTierList(tierListId.value)
|
||||
const t = res.tierList
|
||||
ownerId.value = t.authorId
|
||||
persistedTierListId.value = t.id || ''
|
||||
title.value = t.title
|
||||
thumbnailSrc.value = t.thumbnailSrc || ''
|
||||
description.value = t.description || ''
|
||||
@@ -975,14 +972,6 @@ onUnmounted(() => {
|
||||
<textarea v-model="templateRequestDraftDescription" class="templateRequestDraft__input templateRequestDraft__textarea" maxlength="1000" placeholder="예: 여름 이벤트 한정 캐릭터 추가용으로 신규 템플릿이 필요합니다." />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftDescription.length }}/1000자</span>
|
||||
</label>
|
||||
<label class="toggleSwitch">
|
||||
<input v-model="templateRequestSaveToMyTierList" type="checkbox" />
|
||||
<span class="toggleSwitch__label">내 티어 리스트에도 저장</span>
|
||||
<span class="toggleSwitch__track"><span class="toggleSwitch__thumb"></span></span>
|
||||
</label>
|
||||
<div class="templateRequestDraft__note">
|
||||
저장을 끄면 요청 시점 스냅샷만 관리자에게 전달되고, 내 티어 리스트에는 별도로 남기지 않아요.
|
||||
</div>
|
||||
</div>
|
||||
<div class="modalCard__actions">
|
||||
<button class="btn btn--ghost" @click="closeTemplateRequestModal">취소</button>
|
||||
@@ -1014,14 +1003,6 @@ onUnmounted(() => {
|
||||
<textarea v-model="templateRequestDraftDescription" class="templateRequestDraft__input templateRequestDraft__textarea" maxlength="1000" placeholder="예: 여름 이벤트 한정 캐릭터 추가" />
|
||||
<span class="templateRequestDraft__hint">{{ templateRequestDraftDescription.length }}/1000자</span>
|
||||
</label>
|
||||
<label class="toggleSwitch">
|
||||
<input v-model="templateRequestSaveToMyTierList" type="checkbox" />
|
||||
<span class="toggleSwitch__label">내 티어 리스트에도 저장</span>
|
||||
<span class="toggleSwitch__track"><span class="toggleSwitch__thumb"></span></span>
|
||||
</label>
|
||||
<div class="templateRequestDraft__note">
|
||||
저장을 끄면 관리자 확인용 요청 스냅샷만 남고, 현재 작업 중인 티어표는 따로 저장하지 않아요.
|
||||
</div>
|
||||
</div>
|
||||
<div class="modalCard__actions">
|
||||
<button class="btn btn--ghost" @click="closeTemplateUpdateModal">요청 취소</button>
|
||||
@@ -1285,7 +1266,7 @@ onUnmounted(() => {
|
||||
<div class="editorSidebar__label">커스텀 이름 정리</div>
|
||||
<div class="customItemEditor customItemEditor--sidebar">
|
||||
<div class="customItemEditor__desc">
|
||||
아래에서 이름만 정리해두면 관리자 요청 시 그대로 전달됩니다.
|
||||
아래에서 이름을 정리한 뒤 저장하면, 템플릿 요청 시 그대로 전달됩니다.
|
||||
</div>
|
||||
<div class="customItemEditor__list">
|
||||
<label v-for="item in customItems" :key="item.id" class="customItemEditor__row">
|
||||
|
||||
Reference in New Issue
Block a user