댓글 시스템 복구
This commit is contained in:
@@ -2,8 +2,9 @@
|
||||
import { computed, onBeforeUnmount, onMounted, provide, ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { useAuthStore } from './stores/auth'
|
||||
import { editorNewPath, favoritesPath, followingFeedPath, homePath, loginPath, mePath, templatesPath } from './lib/paths'
|
||||
import { commentsPath, editorNewPath, favoritesPath, followingFeedPath, homePath, loginPath, mePath, templatesPath } from './lib/paths'
|
||||
import { displayInitialFrom } from './lib/display'
|
||||
import { api } from './lib/api'
|
||||
import { toApiUrl } from './lib/runtime'
|
||||
import { useToast } from './composables/useToast'
|
||||
import iconDockToLeft from './assets/icons/dock_to_left.svg'
|
||||
@@ -40,6 +41,7 @@ const viewportWidth = ref(typeof window !== 'undefined' ? window.innerWidth : 14
|
||||
const backendState = ref('online')
|
||||
const backendMessage = ref('')
|
||||
const isFullscreenActive = ref(false)
|
||||
const unreadCommentCount = ref(0)
|
||||
provide('rightRailOpen', rightRailOpen)
|
||||
provide('localRightRailTarget', '#local-right-rail-root')
|
||||
|
||||
@@ -76,6 +78,7 @@ const leftNavItems = computed(() => {
|
||||
{ key: 'me', label: '나의 티어표', path: '/me', iconSrc: iconLists, requiresAuth: true },
|
||||
{ key: 'favorites', label: '즐겨찾기', path: '/favorites', iconSrc: iconFavorite, requiresAuth: true },
|
||||
{ key: 'followingFeed', label: '팔로우 피드', path: '/following', iconSrc: iconKidStar, requiresAuth: true },
|
||||
{ key: 'comments', label: '댓글 관리', path: commentsPath(), iconSrc: iconMenuBook, requiresAuth: true, showDot: unreadCommentCount.value > 0 },
|
||||
{ key: 'profile', label: '설정', path: '/profile', iconSrc: iconSettings, requiresAuth: true },
|
||||
]
|
||||
return items.filter((item) => !item.requiresAuth || (authReady.value && auth.user))
|
||||
@@ -261,6 +264,16 @@ const routeMeta = computed(() => {
|
||||
action: () => router.push(favoritesPath()),
|
||||
}
|
||||
}
|
||||
if (route.name === 'comments') {
|
||||
return {
|
||||
title: '댓글 관리',
|
||||
subtitle: '댓글과 답글 확인',
|
||||
contextTitle: '알림',
|
||||
contextText: '내 티어표에 달린 댓글과 내 댓글에 달린 답글을 확인하고 바로 해당 위치로 이동할 수 있어요.',
|
||||
actionLabel: '나의 티어표 보기',
|
||||
action: () => router.push(mePath()),
|
||||
}
|
||||
}
|
||||
if (route.name === 'userProfile') {
|
||||
return {
|
||||
title: '작성자 프로필',
|
||||
@@ -313,6 +326,23 @@ function handleBackendStatus(event) {
|
||||
backendMessage.value = typeof event?.detail?.message === 'string' ? event.detail.message : ''
|
||||
}
|
||||
|
||||
function handleCommentInboxUpdated(event) {
|
||||
unreadCommentCount.value = Math.max(0, Number(event?.detail?.unreadCount || 0))
|
||||
}
|
||||
|
||||
async function refreshUnreadCommentCount() {
|
||||
if (!authReady.value || !auth.user) {
|
||||
unreadCommentCount.value = 0
|
||||
return
|
||||
}
|
||||
try {
|
||||
const data = await api.getCommentInboxUnreadCount()
|
||||
unreadCommentCount.value = Math.max(0, Number(data.unreadCount || 0))
|
||||
} catch (error) {
|
||||
unreadCommentCount.value = 0
|
||||
}
|
||||
}
|
||||
|
||||
function syncFullscreenState() {
|
||||
if (typeof document === 'undefined') return
|
||||
isFullscreenActive.value = !!(document.fullscreenElement || document.webkitFullscreenElement)
|
||||
@@ -344,6 +374,7 @@ onMounted(async () => {
|
||||
syncViewportWidth()
|
||||
syncFullscreenState()
|
||||
window.addEventListener('tier-maker:backend-status', handleBackendStatus)
|
||||
window.addEventListener('tier-maker:comment-inbox-updated', handleCommentInboxUpdated)
|
||||
window.addEventListener('resize', syncViewportWidth)
|
||||
window.addEventListener('keydown', handleGlobalKeydown)
|
||||
document.addEventListener('fullscreenchange', syncFullscreenState)
|
||||
@@ -360,6 +391,7 @@ onMounted(async () => {
|
||||
rightRailOpen.value = true
|
||||
}
|
||||
searchQuery.value = typeof route.query.q === 'string' ? route.query.q : ''
|
||||
await refreshUnreadCommentCount()
|
||||
})
|
||||
|
||||
function handleGlobalKeydown(event) {
|
||||
@@ -423,6 +455,7 @@ async function toggleFullscreen() {
|
||||
onBeforeUnmount(() => {
|
||||
if (typeof window !== 'undefined') {
|
||||
window.removeEventListener('tier-maker:backend-status', handleBackendStatus)
|
||||
window.removeEventListener('tier-maker:comment-inbox-updated', handleCommentInboxUpdated)
|
||||
window.removeEventListener('resize', syncViewportWidth)
|
||||
window.removeEventListener('keydown', handleGlobalKeydown)
|
||||
document.removeEventListener('fullscreenchange', syncFullscreenState)
|
||||
@@ -441,6 +474,14 @@ watch(
|
||||
mobileLeftNavOpen.value = false
|
||||
rightRailOpen.value = false
|
||||
}
|
||||
refreshUnreadCommentCount()
|
||||
}
|
||||
)
|
||||
|
||||
watch(
|
||||
() => auth.user?.id,
|
||||
() => {
|
||||
refreshUnreadCommentCount()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -656,6 +697,7 @@ function reloadApp() {
|
||||
<span class="leftNav__glyph">
|
||||
<SvgIcon v-if="item.iconSrc" :src="item.iconSrc" :size="24" />
|
||||
<svg v-else viewBox="0 0 24 24" aria-hidden="true"><path :d="item.icon" /></svg>
|
||||
<span v-if="item.showDot" class="leftNav__dot" aria-hidden="true"></span>
|
||||
</span>
|
||||
<span class="leftNav__label">{{ item.label }}</span>
|
||||
</RouterLink>
|
||||
@@ -1260,12 +1302,24 @@ function reloadApp() {
|
||||
/* width: 28px; */
|
||||
/* height: 28px; */
|
||||
/* border-radius: 10px; */
|
||||
position: relative;
|
||||
display: grid;
|
||||
place-items: center;
|
||||
/* background: rgba(255, 255, 255, 0.06); */
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.leftNav__dot {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
right: -3px;
|
||||
width: 9px;
|
||||
height: 9px;
|
||||
border-radius: 999px;
|
||||
background: #ff4d67;
|
||||
box-shadow: 0 0 0 2px var(--theme-surface);
|
||||
}
|
||||
|
||||
.appShell--leftCollapsed .leftRail__top {
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user