From 14dfe0ad75696b89758401fd997593c0e7485375 Mon Sep 17 00:00:00 2001 From: zenn Date: Thu, 2 Apr 2026 15:34:07 +0900 Subject: [PATCH] =?UTF-8?q?=EB=A6=B4=EB=A6=AC=EC=8A=A4:=20v1.3.71=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=EC=9E=90=20=EA=B2=8C=EC=9E=84=20=EC=84=A0?= =?UTF-8?q?=ED=83=9D=20=EB=AA=A8=EB=8B=AC=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/history.md | 4 + docs/todo.md | 1 + docs/update.md | 5 + frontend/src/views/AdminView.vue | 181 ++++++++++++++++++++----------- 4 files changed, 125 insertions(+), 66 deletions(-) diff --git a/docs/history.md b/docs/history.md index 3f8a23b..069e98a 100644 --- a/docs/history.md +++ b/docs/history.md @@ -1,5 +1,9 @@ # 의사결정 이력 +## 2026-04-02 v1.3.71 +- 관리자에서 게임 선택 지점이 늘어나는 구조라면 각 화면마다 셀렉트/긴 리스트를 따로 두기보다, 공용 검색 모달 하나로 통일하는 편이 이후 100개 이상 게임이 쌓여도 더 안정적이라고 정리했다. +- 아이템 모달은 참조 정보 정리 뒤에도 왼쪽 선택 요약 카드가 여전히 과하다고 판단해, 예전처럼 게임 선택 자체에 더 집중한 구조로 한 단계 더 되돌리는 편이 맞다고 판단했다. + ## 2026-04-02 v1.3.70 - 관리자 티어표 목록은 페이지 단위 열람만으로는 운영 개입이 부족하므로, 게임별 필터와 카드 단위 관리 액션을 함께 붙여 실제 검수 도구로 쓰는 편이 맞다고 정리했다. - 공개 여부는 문장 속 메타보다 배지로 따로 떼어 보여주는 편이 다른 관리자 카드들과 문법이 맞고, 공개/비공개 전환도 같은 관리 모달 안에서 바로 처리하는 쪽이 운영 흐름상 자연스럽다고 판단했다. diff --git a/docs/todo.md b/docs/todo.md index 28c304e..f9bf070 100644 --- a/docs/todo.md +++ b/docs/todo.md @@ -1,6 +1,7 @@ # 할 일 및 이슈 ## 단기 확인 +- 공용 `게임 선택` 검색 모달은 새로 붙였으므로, 게임 관리 선택/전체 티어표 관리 필터 양쪽에서 검색어 입력, 선택, 해제, 뒤로가기 흐름을 한 번 더 QA한다. - 관리자 `전체 티어표 관리`의 게임 필터와 관리 모달은 새로 붙였으므로, 실제 운영 데이터에서 필터 전환 후 공개/비공개 집계, 제목 수정, 비공개 전환, 삭제 흐름이 자연스럽게 이어지는지 한 번 더 QA한다. - 관리자 게임 관리 상단의 `전체 / 공개 / 비공개` 티어표 수치와 전체 티어표 관리 상단 집계가 실제 운영 데이터와 맞는지, 공개 전환 직후 숫자가 자연스럽게 갱신되는지 한 번 더 QA한다. - 관리자 아이템 상세 모달은 왼쪽 선택 카드와 오른쪽 상세 본문으로 다시 정리했으므로, 데스크톱/모바일에서 긴 게임 목록과 긴 참조 목록이 각각 자연스럽게 스크롤되는지 한 번 더 QA한다. diff --git a/docs/update.md b/docs/update.md index e1ec78d..89cf1da 100644 --- a/docs/update.md +++ b/docs/update.md @@ -1,5 +1,10 @@ # 업데이트 로그 +## 2026-04-02 v1.3.71 +- 관리자 아이템 모달은 최근 추가했던 선택 요약 카드를 다시 걷어내고, 더 단순한 `게임 선택 패널 + 상세 작업 영역` 구조로 되돌려 이전 흐름에 가깝게 정리함. +- 관리자 `게임 관리`와 `전체 티어표 관리`의 게임 선택은 긴 셀렉트/목록 대신 공용 `게임 선택` 검색 모달로 바꿔, 게임 수가 많아져도 이름·ID 검색으로 바로 찾아 선택할 수 있게 함. +- 전체 티어표 관리의 게임 필터 해제도 같은 모달 흐름에 맞춰 `모든 게임 보기`로 처리하고, 사이드바에는 현재 선택된 게임만 요약 카드로 보여줘 긴 리스트가 계속 쌓이지 않게 정리함. + ## 2026-04-02 v1.3.70 - 관리자 `전체 티어표 관리`는 이제 게임별 필터를 지원해, 특정 게임에서 만들어진 티어표만 따로 골라 보며 공개/비공개 분포를 확인할 수 있게 함. - 전체 티어표 카드는 공개 여부를 텍스트 대신 다른 관리자 화면과 같은 배지 형식으로 표시하고, 카드의 `관리` 액션에서 제목·설명 수정, 공개/비공개 전환, 삭제를 바로 처리할 수 있게 보강함. diff --git a/frontend/src/views/AdminView.vue b/frontend/src/views/AdminView.vue index f8e50bd..5a8b1ce 100644 --- a/frontend/src/views/AdminView.vue +++ b/frontend/src/views/AdminView.vue @@ -34,8 +34,10 @@ const games = ref([]) const selectedGameId = ref('') const selectedGame = ref(null) const featuredGameIds = ref([]) -const gameAdminQuery = ref('') -const gameAdminSort = ref('recent') +const gamePickerModalOpen = ref(false) +const gamePickerMode = ref('game-admin') +const gamePickerQuery = ref('') +const gamePickerSort = ref('recent') const customItems = ref([]) const customItemQuery = ref('') @@ -197,8 +199,8 @@ const featuredGames = computed(() => .filter(Boolean) ) const availableGamesForFeatured = computed(() => games.value.filter((game) => !featuredGameIds.value.includes(game.id))) -const filteredAdminGames = computed(() => { - const query = gameAdminQuery.value.trim().toLowerCase() +const filteredGamePickerGames = computed(() => { + const query = gamePickerQuery.value.trim().toLowerCase() const list = games.value.filter((game) => { if (!query) return true const haystack = `${game.name || ''} ${game.id || ''}`.toLowerCase() @@ -206,7 +208,7 @@ const filteredAdminGames = computed(() => { }) return list.slice().sort((a, b) => { - if (gameAdminSort.value === 'oldest') return Number(a.createdAt || 0) - Number(b.createdAt || 0) + if (gamePickerSort.value === 'oldest') return Number(a.createdAt || 0) - Number(b.createdAt || 0) return Number(b.createdAt || 0) - Number(a.createdAt || 0) }) }) @@ -289,6 +291,7 @@ const adminOverviewStats = computed(() => { const isAnyModalOpen = computed( () => gameCreateModalOpen.value || + gamePickerModalOpen.value || userEditModalOpen.value || userPasswordModalOpen.value || userDeleteModalOpen.value || @@ -1303,6 +1306,30 @@ function setAdminTierListGameId(gameId) { refreshAdminTierLists() } +function openGamePickerModal(mode = 'game-admin') { + gamePickerMode.value = mode + gamePickerQuery.value = '' + gamePickerSort.value = 'recent' + gamePickerModalOpen.value = true +} + +function closeGamePickerModal() { + gamePickerModalOpen.value = false + gamePickerQuery.value = '' +} + +async function chooseGameFromPicker(gameId) { + if (!gameId) return + if (gamePickerMode.value === 'tierlists-filter') { + setAdminTierListGameId(gameId) + closeGamePickerModal() + return + } + + await selectAdminGame(gameId) + closeGamePickerModal() +} + function changeAdminTierListLimit(limit) { adminTierListLimit.value = limit adminTierListPage.value = 1 @@ -1931,16 +1958,6 @@ function userAvatarFallback(user) {