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:
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
<!-- 프로젝트를 찾지 못한 경우 -->
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user