From d3a916dbd7aeb10f02ed1a911358c2b56c5c8255 Mon Sep 17 00:00:00 2001 From: ttipo Date: Mon, 22 Jun 2026 23:49:09 +0900 Subject: [PATCH] =?UTF-8?q?refactor:=20=EC=84=B8=EA=B7=B8=EB=A8=BC?= =?UTF-8?q?=ED=8A=B8=20=ED=86=A0=EA=B8=80=20SegmentedTabs=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=EB=A1=9C=20=ED=86=B5=EC=9D=BC=20(Ph?= =?UTF-8?q?ase=203-1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3개 페이지(활동/프로젝트 상세/멤버)에 반복되던 .segmented 버튼 마크업을 options 기반 SegmentedTabs 로 추출(전역 .segmented 스타일은 그대로 사용). 수량(.n) 표기는 option.count 로 처리. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../src/components/common/SegmentedTabs.vue | 28 +++++++++++++ .../src/pages/relay/ProjectActivityPage.vue | 37 +++++------------ .../src/pages/relay/ProjectDetailPage.vue | 40 +++++++------------ .../src/pages/relay/ProjectMembersPage.vue | 34 +++++++--------- 4 files changed, 67 insertions(+), 72 deletions(-) create mode 100644 frontend/src/components/common/SegmentedTabs.vue diff --git a/frontend/src/components/common/SegmentedTabs.vue b/frontend/src/components/common/SegmentedTabs.vue new file mode 100644 index 0000000..d804d62 --- /dev/null +++ b/frontend/src/components/common/SegmentedTabs.vue @@ -0,0 +1,28 @@ + + + diff --git a/frontend/src/pages/relay/ProjectActivityPage.vue b/frontend/src/pages/relay/ProjectActivityPage.vue index 38a053b..4133c9a 100644 --- a/frontend/src/pages/relay/ProjectActivityPage.vue +++ b/frontend/src/pages/relay/ProjectActivityPage.vue @@ -7,11 +7,18 @@ import ProjectHeader from '@/components/ProjectHeader.vue' 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 { useProjectStore } from '@/stores/project.store' import { useActivityStore } from '@/stores/activity.store' import type { Project, ActivityIcon } from '@/mock/relay.mock' type Filter = 'all' | 'task' | 'member' | 'setting' +const FILTER_OPTIONS: { value: Filter; label: string }[] = [ + { value: 'all', label: '전체' }, + { value: 'task', label: '업무' }, + { value: 'member', label: '멤버' }, + { value: 'setting', label: '설정' }, +] const route = useRoute() const projectId = computed(() => String(route.params.projectId)) @@ -139,32 +146,10 @@ const ActIcon = defineComponent({
-
- - - - -
+ ('all') +// 세그먼트 탭 옵션(수량 포함) — counts 갱신에 반응 +const segOptions = computed<{ value: TaskSegment; label: string; count: number }[]>( + () => [ + { value: 'all', label: '전체', count: counts.value.all }, + { value: 'prog', label: '진행 중', count: counts.value.prog }, + { value: 'todo', label: '대기', count: counts.value.todo }, + { value: 'done', label: '완료', count: counts.value.done }, + ], +) const sort = ref('latest') const SORT_OPTIONS: { value: TaskSort; label: string }[] = [ { value: 'latest', label: '최신순' }, @@ -188,32 +198,10 @@ const STATUS_LABEL: Record = { placeholder="업무 검색…" >
-
- - - - -
+ ({ member: members.value.filter((m) => m.roleType === 'member').length, })) +// 역할 필터 세그먼트 옵션(수량 포함) +const filterOptions = computed<{ value: RoleFilter; label: string; count: number }[]>( + () => [ + { value: 'all', label: '전체', count: counts.value.all }, + { value: 'admin', label: '관리자', count: counts.value.admin }, + { value: 'member', label: '멤버', count: counts.value.member }, + ], +) + const filteredMembers = computed(() => members.value.filter((m) => { const matchRole = filter.value === 'all' || m.roleType === filter.value @@ -286,26 +296,10 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown)) placeholder="이름·이메일 검색…" > -
- - - -
+