diff --git a/frontend/src/assets/styles/relay.css b/frontend/src/assets/styles/relay.css index 495ebff..7ddc9a7 100644 --- a/frontend/src/assets/styles/relay.css +++ b/frontend/src/assets/styles/relay.css @@ -677,3 +677,17 @@ body { opacity: 0.6; cursor: default; } + +/* ============================================================ + * 빈/상태 메시지 박스 (목록 로딩·빈 상태 공통) + * ============================================================ */ +.empty-state { + background: var(--panel); + border: 1px solid var(--border); + border-radius: 0.625rem; + box-shadow: var(--shadow-sm); + padding: 2.5rem 1.25rem; + text-align: center; + font-size: 0.844rem; + color: var(--text-3); +} diff --git a/frontend/src/components/common/EmptyState.vue b/frontend/src/components/common/EmptyState.vue new file mode 100644 index 0000000..977db78 --- /dev/null +++ b/frontend/src/components/common/EmptyState.vue @@ -0,0 +1,10 @@ + + + diff --git a/frontend/src/pages/relay/MyTasksPage.vue b/frontend/src/pages/relay/MyTasksPage.vue index ef0a472..1041eb6 100644 --- a/frontend/src/pages/relay/MyTasksPage.vue +++ b/frontend/src/pages/relay/MyTasksPage.vue @@ -8,6 +8,7 @@ import AppShell from '@/layouts/AppShell.vue' import UserAvatar from '@/components/UserAvatar.vue' import DropdownSelect from '@/components/DropdownSelect.vue' import LoadMore from '@/components/common/LoadMore.vue' +import EmptyState from '@/components/common/EmptyState.vue' import { useMyTaskStore } from '@/stores/my-task.store' import { useProjectStore } from '@/stores/project.store' import { countActive, type MyTaskRow } from '@/mock/relay.mock' @@ -216,18 +217,12 @@ function loadMore() { -
+ 내 업무를 불러오는 중… -
-
+ + {{ view === 'assigned' ? '담당 중인 업무가 없습니다.' : '지시한 업무가 없습니다.' }} -
+
-
+ 활동을 불러오는 중입니다… -
-
+ + 아직 기록된 활동이 없습니다. -
+ @@ -366,15 +361,4 @@ const ActIcon = defineComponent({ margin-left: 0.75rem; } -/* 로딩/빈 상태 */ -.feed-state { - background: var(--panel); - border: 1px solid var(--border); - border-radius: 0.625rem; - box-shadow: var(--shadow-sm); - padding: 2.5rem 1.25rem; - text-align: center; - font-size: 0.844rem; - color: var(--text-3); -} diff --git a/frontend/src/pages/relay/ProjectDetailPage.vue b/frontend/src/pages/relay/ProjectDetailPage.vue index a0a6bbb..fba490a 100644 --- a/frontend/src/pages/relay/ProjectDetailPage.vue +++ b/frontend/src/pages/relay/ProjectDetailPage.vue @@ -11,6 +11,7 @@ import UserAvatar from '@/components/UserAvatar.vue' import DropdownSelect from '@/components/DropdownSelect.vue' import SegmentedTabs from '@/components/common/SegmentedTabs.vue' import LoadMore from '@/components/common/LoadMore.vue' +import EmptyState from '@/components/common/EmptyState.vue' import { useProjectStore } from '@/stores/project.store' import { useTaskStore } from '@/stores/task.store' import type { TaskListQuery, TaskSegment, TaskSort } from '@/types/task' @@ -243,18 +244,12 @@ const STATUS_LABEL: Record = {
-
+ 업무를 불러오는 중… -
-
+ + {{ isFiltered ? '조건에 맞는 업무가 없습니다.' : '아직 등록된 업무가 없습니다. 새 업무를 지시해 보세요.' }} -
+
= { text-align: center; color: var(--text-2); } -.state-msg { - padding: 2.5rem 1.125rem; - text-align: center; - font-size: 0.844rem; - color: var(--text-3); - border: 1px solid var(--border); - border-radius: var(--radius); - background: #fff; -} diff --git a/frontend/src/pages/relay/ProjectListPage.vue b/frontend/src/pages/relay/ProjectListPage.vue index 1089f25..f42a8d8 100644 --- a/frontend/src/pages/relay/ProjectListPage.vue +++ b/frontend/src/pages/relay/ProjectListPage.vue @@ -7,6 +7,7 @@ import AppShell from '@/layouts/AppShell.vue' import UserAvatar from '@/components/UserAvatar.vue' import DropdownSelect from '@/components/DropdownSelect.vue' import LoadMore from '@/components/common/LoadMore.vue' +import EmptyState from '@/components/common/EmptyState.vue' import { useProjectStore } from '@/stores/project.store' import type { ProjectListQuery, ProjectSort } from '@/types/project' @@ -204,18 +205,12 @@ const isFiltered = computed(() => keyword.value.trim() !== '') -
+ 불러오는 중… -
-
+ + {{ isFiltered ? '검색 결과가 없습니다.' : '아직 프로젝트가 없습니다. 새 프로젝트를 만들어 보세요.' }} -
+
@@ -368,10 +363,4 @@ const isFiltered = computed(() => keyword.value.trim() !== '') width: 1.125rem; height: 1.125rem; } -.list-empty { - padding: 2.5rem 1.25rem; - text-align: center; - color: var(--text-3); - font-size: 0.844rem; -} diff --git a/frontend/src/pages/relay/ProjectMembersPage.vue b/frontend/src/pages/relay/ProjectMembersPage.vue index f89970a..c286dfa 100644 --- a/frontend/src/pages/relay/ProjectMembersPage.vue +++ b/frontend/src/pages/relay/ProjectMembersPage.vue @@ -9,6 +9,7 @@ import UserAvatar from '@/components/UserAvatar.vue' import DropdownSelect from '@/components/DropdownSelect.vue' import BaseModal from '@/components/common/BaseModal.vue' import SegmentedTabs from '@/components/common/SegmentedTabs.vue' +import EmptyState from '@/components/common/EmptyState.vue' import { useProjectStore } from '@/stores/project.store' import { useMemberStore } from '@/stores/member.store' import { useUser } from '@/composables/useUser' @@ -325,18 +326,12 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown)) -
+ 멤버를 불러오는 중… -
-
+ + 표시할 멤버가 없습니다. -
+
window.removeEventListener('keydown', onKeydown)) } /* 로딩/빈 상태 메시지 */ -.state-msg { - padding: 2.5rem 1.125rem; - text-align: center; - font-size: 0.844rem; - color: var(--text-3); - border: 1px solid var(--border); - border-radius: var(--radius); - background: #fff; -} /* 역할 변경 드롭다운 */ /* 전역 .list 의 overflow:hidden 이 드롭다운을 잘라내므로, 이 화면에서는 보이도록 해제.