Skip to content

멤버 집계를 GroupHeader 기반으로 변경#56

Merged
ongheong merged 10 commits into
developfrom
fix/MD-41
May 31, 2026
Merged

멤버 집계를 GroupHeader 기반으로 변경#56
ongheong merged 10 commits into
developfrom
fix/MD-41

Conversation

@ongheong
Copy link
Copy Markdown
Contributor

@ongheong ongheong commented May 17, 2026

작업 내용

  • 정산 상세의 완료 상태를 header API의 completedAt 값으로 판정하도록 변경했습니다.
  • 참여자 입금 진행률은 참여자별 정산 상세 API의 isPaid 값을 기준으로 계산합니다.
  • 총무 수동 완료 API PATCH /groups/{code}/complete를 연결했습니다.
  • 모든 참여자가 입금 완료된 경우 총무가 정산 완료 모달에서 완료 처리할 수 있습니다.
  • 이미 완료된 정산에서는 모달 버튼을 닫기 / 확인으로 보여주고, 확인 클릭 시 완료 PATCH를 다시 호출하지 않고 캐릭터 모달만 표시합니다.
  • MSW mock에 header 완료 상태와 참여자 입금 상태 갱신, 수동 완료 API 응답을 반영했습니다.

플로우

  • completedAt 있음: 정산 완료 상태로 처리
  • completedAt 없음 + 마감 지남: 정산 실패 상태로 처리
  • completedAt 없음 + 마감 전: 진행 중 상태로 처리
  • 진행 중 정산에서 전원 입금 완료: 미완료 / 완료 모달 표시, 완료 클릭 시 PATCH 호출
  • 완료된 정산에서 캐릭터 확인: 닫기 / 확인 모달 표시, 확인 클릭 시 PATCH 미호출

검증

  • yarn build 통과

Summary by CodeRabbit

  • 새로운 기능

    • 정산 헤더에 총 멤버 수 및 완료된 멤버 수가 표시됩니다.
    • 정산 완료 요청(종료) 기능 추가로 완료 상태를 반영합니다.
  • 개선 사항

    • 정산 상세 페이지와 헤더의 로딩/상태 반영이 개선되어 변경 후 UI가 빠르게 갱신됩니다.
    • 마감 시간 및 완료 시점 처리와 진행률 계산 로직이 안정화되었습니다.
    • 하단 액션(공유/완료)과 모달 라벨·동작이 상태에 따라 직관적으로 변경되었습니다.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 17, 2026

Review Change Stack

Warning

Review limit reached

@ongheong, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 53 minutes and 5 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 086b5332-2e0d-41df-a9c6-503823a396da

📥 Commits

Reviewing files that changed from the base of the PR and between d69c65b and 0a3063f.

📒 Files selected for processing (2)
  • src/pages/expenseDetail/ExpenseDetailPage.tsx
  • src/pages/expenseDetail/ui/ExpenseTimeHeader/index.tsx
📝 Walkthrough

Walkthrough

GroupHeaderResponse 스키마를 확장(타입 변경 포함)하고, 모킹/API 훅과 컴포넌트(ExpenseDetailPage, ExpenseTimeHeader, BottomAction)의 데이터 흐름을 headerData 중심으로 재구성하며 관련 쿼리 무효화 경로를 확장했습니다.

변경사항

정산 페이지 멤버 집계 리팩토링

Layer / File(s) Summary
GroupHeaderResponse 타입 확장 및 complete API
src/entities/group/model/group.type.ts, src/entities/group/api/group.ts
GroupHeaderResponsedeadline: string, createdAt?: string, `completedAt: string
모킹 핸들러: header 응답·member 업데이트
src/mocks/handlers/group.ts
GET header mock이 getDummyGroupHeader()를 사용해 집계 필드를 포함하도록 변경되고, PATCH /groups/:groupToken/completePUT /groups/:groupToken/members/:id로 더미 completedAt과 member isPaid/paidAt 업데이트 동작이 추가되었습니다.
쿼리 훅과 무효화 경로 확장
src/features/settlement-details/api/useUpdatePaymentStatus.ts, src/features/payment-management/api/useCreatePaymentRequest.ts, src/features/settlement-details/api/useCompleteGroupSettlement.ts
결제 생성/업데이트/정산 완료 훅들이 useQueryClient를 사용하여 성공 시 groupHeader(토큰/코드 기준), profiles, settlementList, memberExpenseDetails 등의 쿼리를 무효화하도록 확장되었습니다.
컴포넌트 데이터 흐름 리팩토링
src/pages/expenseDetail/ExpenseDetailPage.tsx, src/pages/expenseDetail/ui/ExpenseTimeHeader/index.tsx, src/pages/expenseDetail/ui/BottomAction/index.tsx
ExpenseDetailPage가 headerData/isLoading과 member 집계를 상단에서 계산하여 ExpenseTimeHeader와 BottomAction에 주입하도록 변경되었습니다. ExpenseTimeHeader는 주입된 headerData를 사용해 타이머·모달·완료(onCompleteSettlement) 흐름을 제어하고, BottomAction은 isEveryMemberPaid 플래그로 렌더 조건을 판별합니다.

관련 PR

제안 레이블

🔨 Refactor

개요

GroupHeaderResponse 인터페이스에 멤버 집계 필드(totalMemberCount, completedMemberCount)를 추가하고, 이를 통해 ExpenseDetailPage와 ExpenseTimeHeader의 데이터 흐름을 useGetMemberExpenseDetails 기반에서 useGetGroupHeader 기반으로 통합했습니다.

변경사항

정산 페이지 멤버 집계 리팩토링

레이어 / 파일 요약
GroupHeaderResponse 타입 확장
src/entities/group/model/group.type.ts
GroupHeaderResponse 인터페이스에 deadline(string), bank(string), accountNumber(string), totalMemberCount(number), completedMemberCount(number) 필드를 추가하고 deadline 타입을 Date에서 string으로 변경합니다.
쿼리 무효화 및 모킹 응답 업데이트
src/features/settlement-details/api/useUpdatePaymentStatus.ts, src/mocks/handlers/group.ts
결제 상태 업데이트 성공 시 groupHeader 쿼리 무효화를 추가하고, 모킹 응답에 totalMemberCount와 completedMemberCount를 포함하여 API 계약 변경을 반영합니다.
컴포넌트 데이터 흐름 리팩토링
src/pages/expenseDetail/ExpenseDetailPage.tsx, src/pages/expenseDetail/ui/ExpenseTimeHeader/index.tsx
ExpenseDetailPage에서 useGetMemberExpenseDetails를 제거하고 useGetGroupHeader 결과를 headerData와 isLoading으로 ExpenseTimeHeader에 전달합니다. ExpenseTimeHeader는 headerData로부터 totalMember와 paidMember를 계산하고 모달 상태 및 타이머 interval을 관리하는 방식으로 변경됩니다.

관련 PR

  • moddo-kr/moddo-frontend#39: ExpenseDetailPage와 ExpenseTimeHeader의 deadline 및 정산 상태/타이머·모달 제어 로직을 함께 수정하여 코드 경로 충돌이 발생할 수 있습니다.

제안 레이블

🔨 Refactor

토끼가 말이야, 데이터 흐름을 🐰
정산 페이지에서 쭉 펼쳐놨어요,
헤더에서 멤버 집계를 가져와,
컴포넌트가 깔끔하게 받아 처리하지,
모달과 타이머까지 마무리! ⏱️

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/MD-41

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 17, 2026

Deploying moddo-frontend with  Cloudflare Pages  Cloudflare Pages

Latest commit: 0a3063f
Status: ✅  Deploy successful!
Preview URL: https://a329a105.moddo-frontend.pages.dev
Branch Preview URL: https://fix-md-41.moddo-frontend.pages.dev

View logs

# Conflicts:
#	src/pages/expenseDetail/ExpenseDetailPage.tsx
#	src/pages/expenseDetail/ui/ExpenseTimeHeader/index.stories.tsx
#	src/pages/expenseDetail/ui/ExpenseTimeHeader/index.tsx
@ongheong ongheong changed the title fix: use API settlement completion counts @coderabbitai May 17, 2026
@ongheong ongheong marked this pull request as ready for review May 17, 2026 11:56
@github-actions github-actions Bot requested a review from yoouyeon May 17, 2026 11:56
@coderabbitai coderabbitai Bot changed the title @coderabbitai 멤버 집계를 GroupHeader 기반으로 변경 May 17, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/mocks/handlers/group.ts`:
- Around line 110-114: The mocked groupHeader response returned from
HttpResponse.json currently spreads dummyGroups[0] and only adds
totalMemberCount and completedMemberCount, missing required GroupHeaderResponse
fields (totalAmount, deadline, bank, accountNumber); update the return value in
the group handler (where HttpResponse.json and dummyGroups[0] are used) to
include those fields with realistic mock values (or copy them from the existing
dummyGroups entry) so the mock conforms to GroupHeaderResponse and the header UI
no longer shows Invalid Date/undefined.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2eedd46b-f2a7-41bb-bb0a-0350135aee66

📥 Commits

Reviewing files that changed from the base of the PR and between 2700458 and 57ea221.

📒 Files selected for processing (5)
  • src/entities/group/model/group.type.ts
  • src/features/settlement-details/api/useUpdatePaymentStatus.ts
  • src/mocks/handlers/group.ts
  • src/pages/expenseDetail/ExpenseDetailPage.tsx
  • src/pages/expenseDetail/ui/ExpenseTimeHeader/index.tsx

Comment thread src/mocks/handlers/group.ts Outdated
@ongheong ongheong self-assigned this May 17, 2026
@ongheong ongheong marked this pull request as draft May 17, 2026 13:31
@ongheong ongheong marked this pull request as ready for review May 31, 2026 12:10
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (2)
src/pages/expenseDetail/ExpenseDetailPage.tsx (1)

56-57: ⚡ Quick win

currentProfile 매칭 키(id)가 로더와 일치하는지: id 기반 로직은 안전합니다.

  • MemberProfileid: numberuserId: number | null가 모두 존재하므로, undefined === undefined로 인해 find가 첫 요소를 반환하는 상황은 발생하지 않습니다.
  • 로더는 profiles 배열에서 profile.userId === auth.user?.idmyProfile을 고른 뒤 그대로 반환하므로, 페이지의 profiles.find((profile) => profile.id === myProfile.id)는 같은 MemberProfile 객체를 가리키게 됩니다.
  • 다만 ExpenseDetailPage에서 profiles를 다시 조회하므로(중복 fetch) 단순화를 원하면 loaderDatamyProfile을 바로 currentProfile로 사용하는 쪽을 검토할 수 있습니다.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/pages/expenseDetail/ExpenseDetailPage.tsx` around lines 56 - 57, 현재 코드가
profiles.find((profile) => profile.id === myProfile.id) ?? myProfile로
currentProfile을 결정하는데, loader에서 이미 myProfile을 결정해 반환하므로 ExpenseDetailPage 내부에서
중복 조회되는 불필요한 로직입니다; 간단히 currentProfile을 loaderData.myProfile 또는 전달된 myProfile로
직접 사용하도록 변경하여 profiles.find(...) 호출을 제거하고 관련 변수명(currentProfile, profiles,
myProfile, loaderData, ExpenseDetailPage)을 찾아 해당 참조를 교체하세요.
src/entities/group/api/group.ts (1)

49-53: 💤 Low value

파라미터 명명의 일관성을 고려해보세요.

함수 파라미터 이름이 settlementCode이지만, 호출하는 측(useCompleteGroupSettlement)과 다른 API 함수들(getGroupHeader)에서는 모두 groupToken을 사용합니다. 기능상 문제는 없지만, 일관성을 위해 groupToken으로 통일하는 것을 고려해보세요.

♻️ 제안하는 수정
-export const completeGroupSettlement = async (
-  settlementCode: string
-): Promise<void> => {
-  await axiosInstance.patch(`/groups/${settlementCode}/complete`);
+export const completeGroupSettlement = async (
+  groupToken: string
+): Promise<void> => {
+  await axiosInstance.patch(`/groups/${groupToken}/complete`);
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/entities/group/api/group.ts` around lines 49 - 53, Rename the parameter
in completeGroupSettlement from settlementCode to groupToken to match other APIs
(e.g., getGroupHeader) and the caller useCompleteGroupSettlement; update the
function signature export const completeGroupSettlement = async (groupToken:
string): Promise<void> => { ... } and ensure the axiosInstance.patch call uses
`/groups/${groupToken}/complete` so callers and other API functions remain
consistent.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/entities/group/api/group.ts`:
- Around line 49-53: Rename the parameter in completeGroupSettlement from
settlementCode to groupToken to match other APIs (e.g., getGroupHeader) and the
caller useCompleteGroupSettlement; update the function signature export const
completeGroupSettlement = async (groupToken: string): Promise<void> => { ... }
and ensure the axiosInstance.patch call uses `/groups/${groupToken}/complete` so
callers and other API functions remain consistent.

In `@src/pages/expenseDetail/ExpenseDetailPage.tsx`:
- Around line 56-57: 현재 코드가 profiles.find((profile) => profile.id ===
myProfile.id) ?? myProfile로 currentProfile을 결정하는데, loader에서 이미 myProfile을 결정해
반환하므로 ExpenseDetailPage 내부에서 중복 조회되는 불필요한 로직입니다; 간단히 currentProfile을
loaderData.myProfile 또는 전달된 myProfile로 직접 사용하도록 변경하여 profiles.find(...) 호출을 제거하고
관련 변수명(currentProfile, profiles, myProfile, loaderData, ExpenseDetailPage)을 찾아
해당 참조를 교체하세요.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 93714119-829b-4eda-9581-0f7af9043b15

📥 Commits

Reviewing files that changed from the base of the PR and between 57ea221 and d69c65b.

📒 Files selected for processing (8)
  • src/entities/group/api/group.ts
  • src/entities/group/model/group.type.ts
  • src/features/payment-management/api/useCreatePaymentRequest.ts
  • src/features/settlement-details/api/useCompleteGroupSettlement.ts
  • src/mocks/handlers/group.ts
  • src/pages/expenseDetail/ExpenseDetailPage.tsx
  • src/pages/expenseDetail/ui/BottomAction/index.tsx
  • src/pages/expenseDetail/ui/ExpenseTimeHeader/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/expenseDetail/ui/ExpenseTimeHeader/index.tsx

@ongheong ongheong merged commit 610489a into develop May 31, 2026
3 checks passed
@ongheong ongheong deleted the fix/MD-41 branch May 31, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants