fix: 목록 페이지네이션 응답 계약 불일치 및 업무 목록 쿼리 크래시 수정
페이지네이션 도입 후 백엔드 목록 API 가 { items, total, ... } 를 반환하는데
프론트 멤버·업무 소비처가 배열로 기대해 list.map 이 깨지고, 멤버 탭과 업무
목록이 비어 보이던 회귀를 수정.
- backend(task): 업무 목록 쿼리에서 to-many 조인 컬럼(checklist.sort_order)
으로 정렬해 페이지네이션 시 TypeORM 이 터지던 문제 제거(task.seq 만 정렬).
목록 응답은 체크리스트 [완료/전체] 수만 쓰므로 항목 순서가 불필요.
- frontend(member/task): list 컴포저블이 Paginated<T> 를 반환하도록 맞추고
스토어에서 .items 로 언래핑(저장소·내업무와 동일 계약).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -4,15 +4,22 @@ import type {
|
||||
InviteMemberPayload,
|
||||
UpdateMemberPayload,
|
||||
} from '@/types/member'
|
||||
import type { Paginated } from '@/types/pagination'
|
||||
|
||||
// 저장소 멤버 도메인 API Composable — 인터셉터가 success/data 를 언래핑
|
||||
// 경로는 모두 repoId(slugName) 하위: /repos/:repoId/members
|
||||
export function useMember() {
|
||||
const api = useApi()
|
||||
|
||||
// 멤버 목록 (멤버 또는 공개 저장소)
|
||||
async function list(repoId: string): Promise<ApiRepoMember[]> {
|
||||
return (await api.get(`/repos/${repoId}/members`)) as unknown as ApiRepoMember[]
|
||||
// 멤버 목록 (멤버 또는 공개 저장소) — 백엔드가 페이지네이션 { items, total, ... } 반환
|
||||
async function list(
|
||||
repoId: string,
|
||||
page = 1,
|
||||
size = 20,
|
||||
): Promise<Paginated<ApiRepoMember>> {
|
||||
return (await api.get(`/repos/${repoId}/members`, {
|
||||
params: { page, size },
|
||||
})) as unknown as Paginated<ApiRepoMember>
|
||||
}
|
||||
|
||||
// 멤버 초대 (admin) — 가입된 사용자만 이메일로 초대
|
||||
|
||||
@@ -10,17 +10,21 @@ import type {
|
||||
UpdateTaskPayload,
|
||||
} from '@/types/task'
|
||||
import type { TaskStatus } from '@/mock/relay.mock'
|
||||
import type { Paginated } from '@/types/pagination'
|
||||
|
||||
// 업무 도메인 API Composable — 인터셉터가 success/data 를 언래핑
|
||||
// 경로는 모두 repoId(slugName) 하위: /repos/:repoId/tasks[/:taskId]
|
||||
export function useTask() {
|
||||
const api = useApi()
|
||||
|
||||
// 업무 목록 (상태/담당자 필터 선택)
|
||||
async function list(repoId: string, query: TaskListQuery = {}): Promise<ApiRepoTask[]> {
|
||||
// 업무 목록 (상태/담당자 필터 선택) — 백엔드가 페이지네이션 { items, total, ... } 반환
|
||||
async function list(
|
||||
repoId: string,
|
||||
query: TaskListQuery = {},
|
||||
): Promise<Paginated<ApiRepoTask>> {
|
||||
return (await api.get(`/repos/${repoId}/tasks`, {
|
||||
params: query,
|
||||
})) as unknown as ApiRepoTask[]
|
||||
})) as unknown as Paginated<ApiRepoTask>
|
||||
}
|
||||
|
||||
// 업무 단건 상세 (taskId = 저장소 내 순번)
|
||||
|
||||
@@ -45,8 +45,8 @@ export const useMemberStore = defineStore('member', () => {
|
||||
async function fetchList(repoId: string): Promise<void> {
|
||||
loading.value = true
|
||||
try {
|
||||
const list = await memberApi.list(repoId)
|
||||
members.value = list.map((m) => toMemberView(m, currentUserId()))
|
||||
const { items } = await memberApi.list(repoId)
|
||||
members.value = items.map((m) => toMemberView(m, currentUserId()))
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
@@ -211,8 +211,8 @@ export const useTaskStore = defineStore('task', () => {
|
||||
async function fetchList(repoId: string, query: TaskListQuery = {}): Promise<void> {
|
||||
loading.value = true
|
||||
try {
|
||||
const list = await taskApi.list(repoId, query)
|
||||
tasks.value = list.map(toRepoTaskView)
|
||||
const { items } = await taskApi.list(repoId, query)
|
||||
tasks.value = items.map(toRepoTaskView)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user