-
Notifications
You must be signed in to change notification settings - Fork 0
멤버 프로필 컴포넌트 분리 및 API 개선 #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- 크기별 프로필 이미지 컴포넌트 추가 - 스토리 추가
- profile, isPaid, paidAt 타입을 옵셔널로 변경 (falsy값 처리가 되어 있음) - 관련 파일 수정
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the 📝 Walkthrough요약이 PR은 API 요청에서 모킹 옵션을 제거하고, Member 타입 필드를 선택적으로 변경하며, 새로운 MemberProfileImage 컴포넌트를 도입하고 기존 프로필 렌더링 로직을 리팩토링합니다. 변경 사항
관련된 가능성 있는 PR
제안 레이블
시
🚥 Pre-merge checks | ✅ 1✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @src/entities/member/model/member.type.ts:
- Around line 9-11: The isPaid field was made optional causing type mismatches;
revert it to a required boolean to restore compatibility: change isPaid?:
boolean to isPaid: boolean in member.type (Member type), and ensure related
types MemberSettlement.isPaid and UpdatePaymentStatusData.isPaid also use
boolean, and confirm consumers (e.g., ExpenseMemberItem using
useState<boolean>(member.isPaid) and the styled component expecting { isPaid:
boolean }) receive a boolean so no undefined is passed.
In @src/shared/ui/MemberProfileImage/index.tsx:
- Around line 4-7: Change the MemberProfileImageProps so src is optional (src?:
string) and update the component usage to accept possibly undefined src and rely
on the existing runtime fallback (src || defaultProfileImg); specifically modify
the MemberProfileImageProps interface and any places that pass member.profile to
the component (e.g., where MemberProfileImage is used) so TypeScript accepts
optional profile values without error, keeping the existing defaultProfileImg
fallback logic unchanged.
🧹 Nitpick comments (4)
src/entities/auth/api/auth.ts (1)
3-8:expiredAt타입이 실제 응답과 불일치할 수 있습니다.
expiredAt가Date로 정의되어 있지만, JSON 응답에서는 날짜가 문자열로 반환됩니다. axios는 자동으로 Date 객체로 변환하지 않으므로, 실제로는string타입이 반환될 가능성이 높습니다.이 PR 범위를 벗어나지만, 향후
string으로 타입을 변경하거나 응답 처리 시new Date()로 변환하는 것을 고려해 주세요.src/shared/ui/MemberProfileImage/index.tsx (1)
9-11:alt속성 누락으로 접근성 저하.
<img>요소에alt속성이 없으면 스크린 리더 사용자에게 이미지 정보가 전달되지 않습니다. 프로필 이미지임을 나타내는 기본 alt 텍스트를 추가하거나, prop으로 받을 수 있도록 하는 것을 권장합니다.♻️ Proposed fix
-function MemberProfileImage({ src, size }: MemberProfileImageProps) { - return <S.Image src={src || defaultProfileImg} $size={size || 'md'} />; +interface MemberProfileImageProps { + src?: string; + size?: 'sm' | 'md' | 'lg'; + alt?: string; +} + +function MemberProfileImage({ src, size = 'md', alt = '프로필 이미지' }: MemberProfileImageProps) { + return <S.Image src={src || defaultProfileImg} $size={size} alt={alt} />; }src/shared/ui/MemberProfileImage/index.styles.ts (1)
13-18:object-fit: contain대신cover사용을 권장합니다.프로필 이미지(아바타)에서
object-fit: contain을 사용하면 이미지 비율에 따라 원형 영역 내에 빈 공간이 생길 수 있습니다. 원형 아바타를 완전히 채우면서 중앙을 기준으로 자연스럽게 크롭하려면cover가 더 적합합니다.♻️ 권장 수정
export const Image = styled.img<ProfileImgProps>` width: ${(props) => sizeMap[props.$size]}; height: ${(props) => sizeMap[props.$size]}; - object-fit: contain; + object-fit: cover; border-radius: 50%; `;src/shared/ui/MemberProfileImage/index.stories.ts (1)
16-35: 실제 이미지가 포함된 스토리 추가를 고려해 주세요.현재 모든 스토리가 빈
src를 사용하여 fallback 상태만 테스트합니다. 실제 이미지 URL을 사용하는 스토리를 추가하면 이미지 로딩 상태와 렌더링을 시각적으로 검증할 수 있습니다.💡 예시: 실제 이미지가 포함된 스토리
export const WithImage: Story = { args: { src: 'https://picsum.photos/100', size: 'md', }, };
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (12)
src/entities/auth/api/auth.tssrc/entities/group/api/group.tssrc/entities/member/model/member.type.tssrc/features/expense-management/ui/MemberExpenses/index.styles.tssrc/features/expense-management/ui/MemberExpenses/index.tsxsrc/pages/billDetail/ui/ExpenseMemberItem/index.style.tssrc/pages/billDetail/ui/ExpenseMemberItem/index.tsxsrc/pages/memberSetup/ui/AddMember/index.stories.tsxsrc/shared/ui/MemberProfile/index.stories.tssrc/shared/ui/MemberProfileImage/index.stories.tssrc/shared/ui/MemberProfileImage/index.styles.tssrc/shared/ui/MemberProfileImage/index.tsx
💤 Files with no reviewable changes (2)
- src/features/expense-management/ui/MemberExpenses/index.styles.ts
- src/pages/billDetail/ui/ExpenseMemberItem/index.style.ts
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-12-28T04:24:56.857Z
Learnt from: yoouyeon
Repo: moddo-kr/moddo-frontend PR: 12
File: src/pages/login/LoginEntranceView.tsx:13-20
Timestamp: 2025-12-28T04:24:56.857Z
Learning: Guideline: Do not pass raw numbers for spacing props (e.g., gap, padding, margin) to the Flex component. If the design system uses tokenized spacing (theme.unit[...] ), derive spacing from design tokens instead of hard-coded numbers only if the component expects a direct number. In this case, the correct usage is to pass plain numbers (e.g., 16) directly for spacing props used by Flex, rather than theme.unit[16]. Apply this consistently across TSX files where Flex spacing props are used. This improves readability and ensures consistent spacing values align with design tokens.
Applied to files:
src/entities/group/api/group.tssrc/shared/ui/MemberProfileImage/index.styles.tssrc/shared/ui/MemberProfile/index.stories.tssrc/pages/memberSetup/ui/AddMember/index.stories.tsxsrc/entities/auth/api/auth.tssrc/shared/ui/MemberProfileImage/index.tsxsrc/shared/ui/MemberProfileImage/index.stories.tssrc/pages/billDetail/ui/ExpenseMemberItem/index.tsxsrc/features/expense-management/ui/MemberExpenses/index.tsxsrc/entities/member/model/member.type.ts
📚 Learning: 2025-12-28T04:21:15.172Z
Learnt from: yoouyeon
Repo: moddo-kr/moddo-frontend PR: 12
File: src/pages/login/LoginEntranceView.styles.tsx:21-26
Timestamp: 2025-12-28T04:21:15.172Z
Learning: LoginEntranceView.styles.tsx와 LoginPage.styles.ts의 LogoImg styled-component는 상태에 따라 분기되는 독립적인 UI에서 사용되며, 미래에 각각 다르게 변경될 가능성을 고려하여 의도적으로 중복 선언되었다. 이러한 경우 공통 모듈 추출보다 중복 유지가 더 적절한 설계이다.
Applied to files:
src/shared/ui/MemberProfileImage/index.styles.ts
🧬 Code graph analysis (1)
src/entities/auth/api/auth.ts (1)
public/mockServiceWorker.js (1)
response(125-125)
🔇 Additional comments (6)
src/entities/group/api/group.ts (1)
38-44: LGTM!
useMock옵션 제거가 PR 목적에 맞게 올바르게 적용되었습니다. 함수 시그니처와 반환 값 처리가 유지되어 기존 호출 코드에 영향이 없습니다.src/entities/auth/api/auth.ts (1)
10-12: LGTM!
useMock옵션 제거가 PR 목적에 맞게 올바르게 적용되었습니다.group.ts의 변경과 일관성 있게 처리되었습니다.src/shared/ui/MemberProfile/index.stories.ts (1)
22-22: LGTM!
Member타입 변경에 맞춰 스토리 데이터가 올바르게 업데이트되었습니다.Also applies to: 35-35
src/pages/billDetail/ui/ExpenseMemberItem/index.tsx (1)
68-68: LGTM!
MemberProfileImage컴포넌트로의 교체가 깔끔하게 이루어졌습니다. 컴포넌트 내부에서 falsy한src에 대한 폴백 처리가 되어 있어member.profile이 undefined나 빈 문자열이어도 안전하게 동작합니다.src/pages/memberSetup/ui/AddMember/index.stories.tsx (1)
23-23: LGTM!
Member타입 변경에 맞춰 스토리 데이터가 올바르게 업데이트되었습니다.src/features/expense-management/ui/MemberExpenses/index.tsx (1)
17-20: LGTM!MemberProfile 컴포넌트로의 리팩토링이 깔끔합니다. 프로필 렌더링 로직이 공유 컴포넌트로 위임되어 코드 가독성과 재사용성이 향상되었습니다.
리뷰: #16 (comment) - MemberProfile 컴포넌트에서 필요한 props만 받도록 수정 - 타입 변경사항 반영
다른 타입과의 일관성을 유지하기 위함 리뷰: #16 (comment)
리뷰: #16 (comment) - MemberProfile 컴포넌트에서 필요한 props만 받도록 수정 - 타입 변경사항 반영 ...
다른 타입과의 일관성을 유지하기 위함 리뷰: #16 (comment)
4361e33 to
4231dd0
Compare
💻 작업 내용
Member 타입 수정 (좀 더 느슨하게... falsy 값 처리가 가능한 프로퍼티들을 optional로 변경했습니다)(멤버 프로필 컴포넌트 분리 및 API 개선 #16 (comment))
Summary by CodeRabbit
릴리스 노트
리팩터링
Chores
✏️ Tip: You can customize this high-level summary in your review settings.