refactor: 더보기 버튼 LoadMore 컴포넌트로 통일 (Phase 3-2)

목록 페이지네이션 '더보기' 버튼 마크업/문구를 LoadMore 로 추출(전역 .load-more 사용).
- 프로젝트 목록/상세, 내 업무, 프로젝트 활동 4곳 적용
- 활동 화면의 비표준 .more-row/.more-btn 제거하고 표준 .load-more 로 통일
  ('더 보기' → '더보기' 문구도 통일)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-22 23:51:45 +09:00
parent d3a916dbd7
commit e7760e9ddc
5 changed files with 38 additions and 61 deletions
@@ -0,0 +1,17 @@
<script setup lang="ts">
// 목록 페이지네이션 '더보기' 버튼 공용 컴포넌트 — 전역 .load-more 스타일 사용.
// 부모는 보통 v-if="hasMore" 로 노출하고, @load 에서 다음 페이지를 불러온다.
defineProps<{ loading?: boolean }>()
const emit = defineEmits<{ (e: 'load'): void }>()
</script>
<template>
<button
class="load-more"
type="button"
:disabled="loading"
@click="emit('load')"
>
{{ loading ? '불러오는 중…' : '더보기' }}
</button>
</template>
+5 -8
View File
@@ -7,6 +7,7 @@ import { RouterLink } from 'vue-router'
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 { useMyTaskStore } from '@/stores/my-task.store'
import { useProjectStore } from '@/stores/project.store'
import { countActive, type MyTaskRow } from '@/mock/relay.mock'
@@ -412,15 +413,11 @@ function loadMore() {
</div>
<!-- 더보기 -->
<button
<LoadMore
v-if="hasMore"
class="load-more"
type="button"
:disabled="loadingMore"
@click="loadMore"
>
{{ loadingMore ? '불러오는 중…' : '더보기' }}
</button>
:loading="loadingMore"
@load="loadMore"
/>
</div>
</AppShell>
</template>
@@ -8,6 +8,7 @@ import ProjectTabs from '@/components/ProjectTabs.vue'
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 { useProjectStore } from '@/stores/project.store'
import { useActivityStore } from '@/stores/activity.store'
import type { Project, ActivityIcon } from '@/mock/relay.mock'
@@ -228,20 +229,12 @@ const ActIcon = defineComponent({
</div>
</div>
<!-- 보기 서버 페이지네이션(누적). 필터와 무관하게 다음 페이지를 불러온다 -->
<div
<!-- 더보기 서버 페이지네이션(누적). 필터와 무관하게 다음 페이지를 불러온다 -->
<LoadMore
v-if="!loading && activityStore.hasMore"
class="more-row"
>
<button
type="button"
class="more-btn"
:disabled="activityStore.loadingMore"
@click="activityStore.loadMore()"
>
{{ activityStore.loadingMore ? '불러오는 중…' : '더 보기' }}
</button>
</div>
:loading="activityStore.loadingMore"
@load="activityStore.loadMore()"
/>
</div>
</AppShell>
</template>
@@ -373,30 +366,6 @@ const ActIcon = defineComponent({
margin-left: 0.75rem;
}
/* 더 보기 */
.more-row {
display: flex;
justify-content: center;
margin-top: 0.875rem;
}
.more-btn {
border: 1px solid var(--border);
background: var(--panel);
border-radius: 0.5rem;
padding: 0.5rem 1.25rem;
font-size: 0.813rem;
font-weight: 600;
color: var(--text-2);
cursor: pointer;
}
.more-btn:hover:not(:disabled) {
background: #f4f5f7;
}
.more-btn:disabled {
opacity: 0.6;
cursor: default;
}
/* 로딩/빈 상태 */
.feed-state {
background: var(--panel);
@@ -10,6 +10,7 @@ import ProjectTabs from '@/components/ProjectTabs.vue'
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 { useProjectStore } from '@/stores/project.store'
import { useTaskStore } from '@/stores/task.store'
import type { TaskListQuery, TaskSegment, TaskSort } from '@/types/task'
@@ -405,15 +406,11 @@ const STATUS_LABEL: Record<TaskStatus, string> = {
</div>
<!-- 더보기 -->
<button
<LoadMore
v-if="hasMore"
class="load-more"
type="button"
:disabled="loadingMore"
@click="loadMoreTasks()"
>
{{ loadingMore ? '불러오는 중…' : '더보기' }}
</button>
:loading="loadingMore"
@load="loadMoreTasks"
/>
</div>
<!-- 프로젝트를 찾지 못한 경우 -->
+5 -8
View File
@@ -6,6 +6,7 @@ import { RouterLink } from 'vue-router'
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 { useProjectStore } from '@/stores/project.store'
import type { ProjectListQuery, ProjectSort } from '@/types/project'
@@ -218,15 +219,11 @@ const isFiltered = computed(() => keyword.value.trim() !== '')
</div>
<!-- 더보기 -->
<button
<LoadMore
v-if="hasMore"
class="load-more"
type="button"
:disabled="loadingMore"
@click="projectStore.loadMore()"
>
{{ loadingMore ? '불러오는 중…' : '더보기' }}
</button>
:loading="loadingMore"
@load="projectStore.loadMore()"
/>
</div>
</AppShell>
</template>