Skip to content

Feature#137 : 마이페이지 디테일 수정 및 이전 활동내역 작업 완료#138

Closed
TaeseongYun wants to merge 7 commits intorelease/v1.1.0from
feature#137-mypage-detail
Closed

Feature#137 : 마이페이지 디테일 수정 및 이전 활동내역 작업 완료#138
TaeseongYun wants to merge 7 commits intorelease/v1.1.0from
feature#137-mypage-detail

Conversation

@TaeseongYun
Copy link
Contributor

@TaeseongYun TaeseongYun commented Apr 25, 2025

💡 Issue

🌱 Key changes

마이페이지 디테일 수정 및 이전 활동내역 작업 완료

✅ To Reviewers

📸 스크린샷

Screen_recording_20250426_181657.mp4

Summary by CodeRabbit

  • 신규 기능

    • 프로필 화면에서 '이전 활동 내역'을 확인할 수 있는 화면 및 내비게이션이 추가되었습니다.
    • 이전 활동 내역 화면에서 활동 이력 리스트와 상세 정보를 확인할 수 있습니다.
    • 프로필 화면에 회원 탈퇴(계정 삭제) 확인 다이얼로그가 추가되었습니다.
    • 프로필 정보에 프로필 아이콘이 표시됩니다.
    • 세션 출석 타입에 OFFLINE, TEAM 옵션이 추가되었습니다.
  • 버그 수정

    • 세션 목록 데이터 구조가 개선되어 여러 세션을 한 번에 처리할 수 있습니다.
  • 문서 및 리소스

    • '이전 활동 내역', 회원 탈퇴 관련 다이얼로그 등 신규 문자열 리소스가 추가되었습니다.
  • 리팩터 및 스타일

    • 일부 패키지 구조 및 코드 정리가 이루어졌습니다.

@TaeseongYun TaeseongYun added Feature 기능 추가, 개발 CodeRabbit CodeRabbit 코드 리뷰 요청 labels Apr 25, 2025
@TaeseongYun TaeseongYun requested a review from DongChyeon April 25, 2025 07:40
@TaeseongYun TaeseongYun self-assigned this Apr 25, 2025
@coderabbitai
Copy link

coderabbitai bot commented Apr 25, 2025

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

이번 변경 사항은 마이페이지(프로필)에서 '이전 활동 내역'을 확인할 수 있는 새로운 히스토리 기능을 추가하고, 세션 API 구조를 응답 객체의 구조 변경에 맞게 리팩토링하였습니다. 또한, 프로필 화면에 회원 탈퇴 다이얼로그 및 관련 인텐트/사이드이펙트를 추가하고, 프로필 정보 섹션에 프로필 이미지를 표시하도록 개선하였습니다. 이외에도 히스토리 및 프로필 관련 패키지 구조를 정비하고, 새로운 도메인 모델과 API, UI 컴포넌트가 추가되었습니다.

Changes

파일/경로 요약 변경 요약
app/src/main/java/com/yapp/app/official/navigation/YappNavHost.kt, app/src/main/java/com/yapp/app/official/ui/Navigator.kt 이전 활동 내역(PreviousHistory) 네비게이션 그래프 및 이동 함수 추가, 프로필에서 해당 화면으로 이동하도록 연결
core/data-api/.../UserRepository.kt, core/data/.../repository/UserRepositoryImpl.kt, core/data/.../api/UserApi.kt, core/data/.../model/response/UserActivityHistoryResponse.kt, core/model/.../ActivityHistory.kt, feature/history/previous/* 사용자 활동 이력(PreviousHistory) 도메인/데이터/뷰모델/유즈케이스/컴포넌트 일괄 추가 및 연결
core/data/.../api/SessionApi.kt, core/data/.../repository/SessionsRepositoryImpl.kt, core/data/.../model/response/SessionResponse.kt, core/model/.../Sessions.kt 세션 API 응답 구조 변경(단일 객체→리스트 포함 객체), AttendType enum 값 추가, 내부 매핑 로직 수정
feature/history/attend/*, feature/history/attend/components/* attend 관련 패키지 구조 정비(하위 디렉토리로 이동), import 경로 수정
feature/history/navigation/HistoryNavigatoion.kt PreviousHistory 네비게이션 목적지, 이동 함수, 그래프 빌더 추가
feature/history/previous/HistoryItems.kt, feature/history/previous/PreviousHistoryScreen.kt 이전 활동 내역 UI 컴포넌트 및 스크린 추가
feature/profile/src/main/java/com/yapp/feature/profile/ProfileContract.kt, ProfileScreen.kt, ProfileViewModel.kt 탈퇴 다이얼로그 관련 인텐트, 사이드이펙트, UI, 뷰모델 로직 추가 및 프로필에서 이전 활동 내역 이동 인텐트 연결
feature/profile/src/main/java/com/yapp/feature/profile/component/ProfileInformationSection.kt 프로필 이미지 표시 기능 추가
feature/history/src/main/res/values/strings.xml, feature/profile/src/main/res/values/string.xml 이전 활동 내역 및 탈퇴 다이얼로그 관련 string 리소스 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant ProfileScreen
    participant ProfileViewModel
    participant Navigator
    participant PreviousHistoryScreen
    participant PreviousHistoryViewModel
    participant UserRepository

    User->>ProfileScreen: '이전 활동 내역' 버튼 클릭
    ProfileScreen->>ProfileViewModel: OnClickPreviousHistory Intent
    ProfileViewModel->>Navigator: navigateToPreviousHistory()
    Navigator->>PreviousHistoryScreen: 네비게이션 이동
    PreviousHistoryScreen->>PreviousHistoryViewModel: OnEntryScreen Intent
    PreviousHistoryViewModel->>UserRepository: getUserActivityHistories()
    UserRepository-->>PreviousHistoryViewModel: ActivityHistory Flow
    PreviousHistoryViewModel->>PreviousHistoryScreen: 상태 업데이트 (PreviousHistoryState)
    User->>PreviousHistoryScreen: 뒤로가기 클릭
    PreviousHistoryScreen->>PreviousHistoryViewModel: OnClickBackButton Intent
    PreviousHistoryViewModel->>PreviousHistoryScreen: Finish SideEffect
    PreviousHistoryScreen->>Navigator: popBackStack()
Loading

Assessment against linked issues

Objective Addressed Explanation
마이페이지 세션 API 작업 및 디테일 수정 (#137)

Possibly related PRs

Poem

🐰
마이페이지에 새 길이 났어요,
이전 활동 내역, 이제 한눈에 보여요!
프로필 속 귀여운 토끼 얼굴도
탈퇴할 땐 조심, 다이얼로그로 묻고
세션 API도 한층 더 단단하게
오늘도 코드밭에 당근 한 움큼,
야무지게 달려가는 토끼의 하루!


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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

‼️ IMPORTANT
Auto-reply has been disabled for this repository in the CodeRabbit settings. The CodeRabbit bot will not respond to your replies unless it is explicitly tagged.

  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@TaeseongYun
Copy link
Contributor Author

현재 코드 입력 부분에서 500 에러가 발생하고 있어 영상을 따로 찍지 못했습니다.

영상 처리가 완료되면 리뷰는 준비상태로 처리하겠습니다.

@TaeseongYun TaeseongYun marked this pull request as draft April 25, 2025 07:41
@TaeseongYun TaeseongYun requested a review from jinukeu April 26, 2025 09:18
@TaeseongYun TaeseongYun marked this pull request as ready for review April 26, 2025 09:18
@TaeseongYun
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Apr 26, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@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: 11

🔭 Outside diff range comments (1)
feature/history/src/main/java/com/yapp/feature/history/navigation/HistoryNavigatoion.kt (1)

1-39: 🧹 Nitpick (assertive)

파일명에 오타가 있습니다.

파일 이름이 HistoryNavigatoion.kt로 되어 있는데, 올바른 철자는 HistoryNavigation.kt입니다.

파일 이름을 수정해주세요.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e7d409 and c2e7a5a.

📒 Files selected for processing (30)
  • app/src/main/java/com/yapp/app/official/navigation/YappNavHost.kt (2 hunks)
  • app/src/main/java/com/yapp/app/official/ui/Navigator.kt (2 hunks)
  • core/data-api/src/main/java/com/yapp/dataapi/UserRepository.kt (1 hunks)
  • core/data/src/main/java/com/yapp/core/data/data/repository/SessionsRepositoryImpl.kt (1 hunks)
  • core/data/src/main/java/com/yapp/core/data/data/repository/UserRepositoryImpl.kt (2 hunks)
  • core/data/src/main/java/com/yapp/core/data/remote/api/SessionApi.kt (1 hunks)
  • core/data/src/main/java/com/yapp/core/data/remote/api/UserApi.kt (2 hunks)
  • core/data/src/main/java/com/yapp/core/data/remote/model/response/SessionResponse.kt (1 hunks)
  • core/data/src/main/java/com/yapp/core/data/remote/model/response/UserActivityHistoryResponse.kt (1 hunks)
  • core/model/src/main/java/com/yapp/model/ActivityHistory.kt (1 hunks)
  • core/model/src/main/java/com/yapp/model/Sessions.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryContract.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryScreen.kt (2 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryUseCase.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryViewModel.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/attend/components/AttendanceStatusSession.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/attend/components/SessionAttendanceItem.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/attend/components/StatusItem.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/navigation/HistoryNavigatoion.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/previous/HistoryItems.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryContract.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryScreen.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryUseCase.kt (1 hunks)
  • feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryViewModel.kt (1 hunks)
  • feature/history/src/main/res/values/strings.xml (1 hunks)
  • feature/profile/src/main/java/com/yapp/feature/profile/ProfileContract.kt (1 hunks)
  • feature/profile/src/main/java/com/yapp/feature/profile/ProfileScreen.kt (2 hunks)
  • feature/profile/src/main/java/com/yapp/feature/profile/ProfileViewModel.kt (3 hunks)
  • feature/profile/src/main/java/com/yapp/feature/profile/component/ProfileInformationSection.kt (2 hunks)
  • feature/profile/src/main/res/values/string.xml (1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
app/src/main/java/com/yapp/app/official/navigation/YappNavHost.kt (1)
feature/history/src/main/java/com/yapp/feature/history/navigation/HistoryNavigatoion.kt (2)
  • attendanceHistoryNavGraph (24-30)
  • previousHistoryNavGraph (32-38)
feature/profile/src/main/java/com/yapp/feature/profile/ProfileScreen.kt (1)
core/designsystem/src/main/java/com/yapp/core/designsystem/component/alert/YappAlertDialog.kt (1)
  • YappAlertDialog (23-91)
feature/history/src/main/java/com/yapp/feature/history/navigation/HistoryNavigatoion.kt (2)
feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryScreen.kt (1)
  • AttendHistoryRoute (31-65)
feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryScreen.kt (1)
  • PreviousHistoryRoute (29-54)
feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryScreen.kt (3)
core/ui/src/main/java/com/yapp/core/ui/component/YappBackground.kt (1)
  • YappBackground (10-22)
feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryContract.kt (1)
  • items (3-12)
feature/history/src/main/java/com/yapp/feature/history/previous/HistoryItems.kt (1)
  • HistoryItems (21-37)
feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryViewModel.kt (1)
core/ui/src/main/java/com/yapp/core/ui/mvi/MviIntentStore.kt (1)
  • mviIntentStore (53-60)
🔇 Additional comments (45)
core/model/src/main/java/com/yapp/model/Sessions.kt (1)

14-14: AttendType에 새로운 열거형 상수 추가

새로운 OFFLINETEAM 유형이 AttendType 열거형에 추가되었습니다. 이는 세션 데이터 처리에 대한 더 넓은 변경과 일치하며, 오프라인 및 팀 세션을 포함한 다양한 세션 유형을 지원합니다.

core/data/src/main/java/com/yapp/core/data/remote/api/SessionApi.kt (1)

8-8: API 응답 구조 변경 적용

반환 타입이 List<SessionResponse>에서 단일 SessionResponse 객체로 변경되었습니다. 이는 API 설계의 변화를 반영하며, 여러 세션 응답 객체 대신 여러 세션을 포함하는 단일 응답 객체를 반환하는 방식으로 변경되었습니다.

core/data/src/main/java/com/yapp/core/data/data/repository/SessionsRepositoryImpl.kt (1)

13-13: 새로운 API 응답 구조에 맞게 구현 업데이트

API 응답 구조 변경에 맞게 리포지토리 구현이 업데이트되었습니다. 이제 sessionApi.getSessions()는 단일 SessionResponse 객체를 반환하며, 이 객체 내의 sessions 리스트를 매핑하여 도메인 모델로 변환합니다.

core/data/src/main/java/com/yapp/core/data/remote/model/response/SessionResponse.kt (1)

7-20: SessionResponse 데이터 클래스 구조 리팩토링

SessionResponse 데이터 클래스가 여러 세션을 캡슐화하도록 리팩토링되었습니다. 기존의 평면적인 구조에서 새로 도입된 중첩된 Session 데이터 클래스의 목록을 포함하는 단일 속성 sessions으로 변경되었습니다. 이 변경은 API 설계의 변화와 일치하며, 더 효율적인 세션 데이터 관리를 가능하게 합니다.

feature/history/src/main/java/com/yapp/feature/history/attend/components/SessionAttendanceItem.kt (1)

1-1: 패키지 선언 일치화
패키지 경로를 com.yapp.feature.history.attend.components로 업데이트하여 모듈 구조와 파일 위치가 일치하도록 정리되었습니다.

feature/history/src/main/res/values/strings.xml (1)

15-15: 이전 활동 내역 문자열 리소스 추가
PreviousHistoryScreen의 타이틀로 사용되는 previous_title 리소스를 추가했습니다.

feature/profile/src/main/res/values/string.xml (1)

13-15: 회원 탈퇴 다이얼로그 문자열 리소스 추가
다이얼로그 타이틀(profile_withdraw_dialog_title), 메시지(profile_withdraw_dialog_message), 버튼 레이블(profile_withdraw_dialog_recommend_button)을 추가하여 탈퇴 확인 UI에 필요한 문자열을 정의했습니다.

feature/history/src/main/java/com/yapp/feature/history/attend/components/AttendanceStatusSession.kt (1)

1-1: 패키지 선언 경로 수정
AttendanceStatusSession.kt의 패키지 선언을 com.yapp.feature.history.attend.components로 일관성 있게 변경했습니다.

feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryContract.kt (1)

1-1: 패키지 경로 리팩토링
AttendHistoryContract.kt의 패키지를 com.yapp.feature.history.attend로 이동하여 참석 내역 기능 모듈과 분리했습니다.

feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryUseCase.kt (1)

1-1: 패키지 구조 정리 작업이 잘 이루어졌습니다.

패키지를 com.yapp.feature.history에서 com.yapp.feature.history.attend로 변경하여 기능별 모듈화가 잘 이루어졌습니다. 이런 구조 변경은 코드의 가독성과 유지보수성을 높이는 좋은 접근법입니다.

feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryViewModel.kt (1)

1-1: 패키지 구조 변경이 일관성 있게 적용되었습니다.

AttendHistoryViewModel의 패키지를 com.yapp.feature.history.attend로 변경함으로써 관련 기능들이 논리적으로 그룹화되었습니다. 이는 참석 기록과 이전 활동 내역 기능을 명확히 분리하는 좋은 구조입니다.

feature/history/src/main/java/com/yapp/feature/history/attend/components/StatusItem.kt (1)

1-1: 컴포넌트 패키지 구조가 체계적으로 정리되었습니다.

StatusItem 컴포넌트의 패키지를 com.yapp.feature.history.components에서 com.yapp.feature.history.attend.components로 변경하여 기능별 UI 컴포넌트 구조화가 잘 이루어졌습니다. 이러한 변경은 전체 구조 개선 작업과 일관성이 있으며, 다른 기능과의 분리도 명확해졌습니다.

app/src/main/java/com/yapp/app/official/ui/Navigator.kt (2)

17-17: 새로운 네비게이션 기능 추가가 잘 구현되었습니다.

이전 활동 내역 화면으로 이동하기 위한 navigateToPreviousHistory 임포트가 적절하게 추가되었습니다.


90-92: 이전 활동 내역 네비게이션 기능이 일관된 패턴으로 추가되었습니다.

navigateToPreviousHistory() 메소드가 기존 네비게이션 메소드들과 동일한 패턴으로 구현되어 일관성을 유지하고 있습니다. 함수 구현이 간결하고 목적에 맞게 잘 설계되었습니다.

feature/history/src/main/java/com/yapp/feature/history/attend/AttendHistoryScreen.kt (1)

1-1: 패키지 구조 개선이 잘 이루어졌습니다!

출석 내역 관련 코드를 com.yapp.feature.history.attend 패키지로 이동시켜 코드베이스의 구조가 개선되었습니다. 이는 '이전 활동 내역' 기능이 추가됨에 따라 History 모듈을 기능별로 더 명확하게 구분한 것으로 보입니다. 관련 임포트 경로도 모두 정확하게 업데이트되었습니다.

Also applies to: 21-28

core/data/src/main/java/com/yapp/core/data/data/repository/UserRepositoryImpl.kt (2)

6-6: 필요한 도메인 모델 import 추가

ActivityHistory 도메인 모델을 import하여 사용자 활동 내역 조회 기능을 지원합니다.


26-28: 사용자 활동 내역 조회 기능 구현 완료

getUserActivityHistories 함수는 Flow를 반환하도록 적절히 구현되었습니다. API 호출 결과를 도메인 모델로 변환하여 반환하는 패턴을 잘 따르고 있습니다.

app/src/main/java/com/yapp/app/official/navigation/YappNavHost.kt (3)

11-11: 이전 활동 내역 관련 네비게이션 그래프 import 추가

previousHistoryNavGraph를 import하여 이전 활동 내역 화면으로의 네비게이션을 지원합니다.


85-85: 프로필에서 활동 내역 화면으로 네비게이션 설정

프로필 화면에서 이전 활동 내역 화면으로 이동하는 네비게이션 콜백이 적절히 구현되었습니다.


91-93: 이전 활동 내역 네비게이션 그래프 추가

이전 활동 내역 화면으로의 네비게이션 그래프가 적절히 추가되었으며, 뒤로 가기 기능도 올바르게 구현되었습니다. 이는 HistoryNavigatoion.kt에 정의된 네비게이션 그래프와 일관성 있게 통합되었습니다.

core/model/src/main/java/com/yapp/model/ActivityHistory.kt (1)

3-12: 활동 내역을 위한 도메인 모델 구현

ActivityHistory 도메인 모델이 적절하게 구현되었습니다. 기수, 포지션, 활동 시작일, 활동 종료일 정보를 포함하는 내부 클래스 Unit을 통해 사용자 활동 내역 정보를 효과적으로 캡슐화하고 있습니다.

하나 고려할 점은 activityStartDateactivityEndDate가 nullable로 선언되어 있는데, 이러한 설계 선택이 의도적인지 확인해보세요. 만약 이 필드들이 비즈니스 로직에서 항상 존재해야 하는 값이라면 non-nullable로 변경하는 것이 더 안전할 수 있습니다.

feature/profile/src/main/java/com/yapp/feature/profile/ProfileScreen.kt (2)

80-90: 회원 탈퇴 다이얼로그 구현

회원 탈퇴 다이얼로그가 적절히 구현되었습니다. 제목, 본문 메시지, 버튼 텍스트 등 리소스를 활용하여 지역화를 고려했고, 각 액션에 적절한 인텐트를 연결했습니다.


98-101: 프로필 화면 액션 인텐트 연결

프로필 화면의 이전 활동 내역, 사용 방법, 회원 탈퇴 버튼에 대한 인텐트 처리가 적절히 구현되었습니다.

feature/profile/src/main/java/com/yapp/feature/profile/ProfileContract.kt (2)

25-26: 회원 탈퇴 관련 새로운 인텐트 추가 확인

회원 탈퇴 기능을 위한 두 가지 인텐트가 적절하게 추가되었습니다. 네이밍이 기존의 인텐트 패턴과 일관성을 유지하고 있어 좋습니다.


34-34: 사용법 화면 이동을 위한 사이드 이펙트 추가 확인

NavigateToUsage 사이드 이펙트가 잘 추가되었습니다. 이 사이드 이펙트는 프로필 화면에서 사용법 화면으로의 네비게이션을 처리하는 데 사용될 것입니다.

feature/history/src/main/java/com/yapp/feature/history/previous/HistoryItems.kt (1)

39-50: 프리뷰 함수 검토

프리뷰 함수가 잘 구현되어 있습니다. 컴포저블의 모습을 미리 확인할 수 있도록 적절한 샘플 데이터를 사용하고 있습니다.

feature/profile/src/main/java/com/yapp/feature/profile/ProfileViewModel.kt (4)

9-11: 필요한 의존성 추가 확인

회원 탈퇴 및 로그아웃 기능에 필요한 DeleteAccountUseCaseLogoutUseCase 의존성이 잘 추가되었습니다.


22-26: 뷰모델 생성자 수정 검토

새로운 의존성이 생성자에 잘 추가되었습니다. 각 의존성의 private 접근 제한자가 일관되게 적용되어 있어 좋습니다.


46-50: 회원 탈퇴 취소 처리 확인

회원 탈퇴 취소 인텐트 처리가 잘 구현되어 있습니다. 다이얼로그 상태를 토글하는 논리가 명확하고 간결합니다.


51-53: 사용법 화면 이동 처리 확인

사용법 화면으로 이동하는 로직이 상태 변경 없이 사이드 이펙트만 발생시키도록 변경되었습니다. 이는 단순 네비게이션에 적합한 구현입니다.

feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryContract.kt (2)

1-22: 계약 클래스 구조가 잘 설계되었습니다.

MVI 아키텍처 패턴에 맞게 상태(State), 사이드 이펙트(SideEffect), 인텐트(Intent)가 명확하게 분리되어 있습니다. 각 구성 요소의 역할이 명확하고 단일 책임 원칙을 잘 따르고 있습니다.


9-10: 날짜 필드가 nullable로 선언된 이유를 검토해주세요.

activityStartDateactivityEndDate가 nullable로 선언되어 있습니다. 이는 의도적인 설계일 수 있으나, UI에서 null 처리 로직이 필요할 수 있습니다. 이 필드들이 어떤 상황에서 null이 될 수 있는지 문서화하거나 주석을 추가하는 것이 좋을 것 같습니다.

feature/history/src/main/java/com/yapp/feature/history/navigation/HistoryNavigatoion.kt (4)

6-7: 필요한 import 구문이 적절히 추가되었습니다.

필요한 Route 클래스들이 올바르게 임포트되었습니다.


13-14: PreviousHistory 네비게이션 대상이 적절하게 정의되었습니다.

기존 AttendanceHistory와 일관된 방식으로 PreviousHistory 네비게이션 대상이 정의되었습니다.


20-22: 네비게이션 확장 함수가 일관성 있게 구현되었습니다.

기존 코드 스타일과 일치하게 네비게이션 확장 함수가 구현되었습니다.


32-38: 네비게이션 그래프 추가가 적절합니다.

previousHistoryNavGraph 함수가 기존 attendanceHistoryNavGraph 패턴을 따라 일관성 있게 구현되었습니다. 네비게이션 콜백도 적절하게 전달되고 있습니다.

core/data/src/main/java/com/yapp/core/data/remote/model/response/UserActivityHistoryResponse.kt (3)

6-17: 응답 모델 구조가 적절합니다.

UserActivityHistoryResponse 클래스와 내부 Unit 클래스의 구조가 잘 설계되었습니다. 필요한 필드들이 포함되어 있고, @Serializable 어노테이션도 적절히 사용되었습니다.


18-29: 도메인 모델 변환 메서드가 적절하게 구현되었습니다.

toModel() 메서드를 통해 응답 모델을 도메인 모델로 변환하는 로직이 깔끔하게 구현되었습니다. 각 필드가 적절히 매핑되고 있습니다.


14-15: 날짜 필드가 nullable로 선언된 이유를 검토해주세요.

activityStartDateactivityEndDate가 nullable로 선언되어 있습니다. API 응답에서 이 필드들이 실제로 null이 올 수 있는지 확인해주세요. 백엔드 API와의 일관성을 위해 필요하다면 주석을 통해 이유를 설명하는 것이 좋을 것 같습니다.

feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryViewModel.kt (2)

14-23: ViewModel 구조와 DI 설정이 적절합니다.

@HiltViewModel 어노테이션과 의존성 주입이 올바르게 설정되었습니다. MviIntentStore를 사용하여 상태 관리를 구현한 것도 아키텍처에 부합합니다.


24-44: 인텐트 핸들러가 적절하게 구현되었습니다.

각 인텐트에 대한 처리 로직이 명확하게 구현되어 있습니다. 특히 OnEntryScreen 인텐트 처리 시 오류 처리(catch), 상태 업데이트(reduce), 비동기 처리(launchIn)가 모두 적절하게 구현되어 있습니다.

feature/history/src/main/java/com/yapp/feature/history/previous/PreviousHistoryScreen.kt (2)

29-54: MVI 패턴이 잘 구현되어 있습니다.

Route 컴포저블이 ViewModel과 UI를 효과적으로 연결하고 있습니다. ViewModel의 상태를 수집하고, Intent를 발생시키며, SideEffect를 처리하는 부분이 잘 구현되어 있습니다. collectAsStateWithLifecycle을 사용하여 생명주기를 고려한 상태 수집을 하는 점도 좋습니다.


56-73: UI 구조가 깔끔하게 구성되어 있습니다.

YappBackground와 Column을 사용하여 화면 레이아웃을 효과적으로 구성했습니다. YappHeaderActionbar를 통해 상단 헤더와 뒤로 가기 버튼을 적절히 배치하고, LazyColumn을 사용하여 스크롤 가능한 목록을 표시하는 방식이 좋습니다.

core/data-api/src/main/java/com/yapp/dataapi/UserRepository.kt (1)

3-3: 새로운 ActivityHistory 도메인 모델과 메소드 추가 확인.

ActivityHistory 모델을 가져오는 import와 사용자 활동 내역을 가져오는 getUserActivityHistories() 메소드가 적절히 추가되었습니다. 이 변경 사항은 PR 설명에 언급된 "이전 활동 내역" 기능 완료와 일치합니다.

Also applies to: 11-11

core/data/src/main/java/com/yapp/core/data/remote/api/UserApi.kt (1)

3-3: 새로운 활동 내역 API 엔드포인트 추가.

사용자 활동 내역을 가져오는 API 엔드포인트가 적절히 추가되었습니다. 엔드포인트 경로와 메소드 명명법이 RESTful 규칙을 따르고 있어 일관된 API 설계를 유지하고 있습니다.

Also applies to: 14-16

Comment on lines +62 to +64
SideEffect.NavigateToUsage -> {

}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

사용 방법 네비게이션 사이드 이펙트 추가

NavigateToUsage 사이드 이펙트 처리가 추가되었지만, 현재 구현 내용이 비어 있습니다. 향후 구현 예정이라면 TODO 주석을 추가하거나, 구현을 완료하는 것이 좋겠습니다.

SideEffect.NavigateToUsage -> {
-
+    // TODO: 사용 방법 화면으로 네비게이션 구현 필요
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
SideEffect.NavigateToUsage -> {
}
SideEffect.NavigateToUsage -> {
// TODO: 사용 방법 화면으로 네비게이션 구현 필요
}

Comment on lines +21 to +37
@Composable
internal fun HistoryItems(
modifier: Modifier = Modifier,
generation: Int,
position: String,
slot: @Composable (() -> Unit)? = null
) {
Column(modifier = modifier.fillMaxWidth()) {
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
Text(modifier = Modifier.weight(1f), text = position, style = YappTheme.typography.heading2Bold)
Image(painter = painterResource(coreDesignR.drawable.icon_yapp), contentDescription = null)
Text("${generation}기", style = YappTheme.typography.label1NormalMedium)
}

slot?.invoke()
}
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

히스토리 아이템 컴포넌트 구현 검토

히스토리 항목을 표시하기 위한 컴포넌트가 잘 구현되어 있습니다. 다만 몇 가지 개선할 점이 있습니다:

  1. Image 컴포넌트의 contentDescriptionnull입니다. 접근성을 위해 적절한 설명을 추가하는 것이 좋습니다.
  2. 함수에 KDoc 문서화 주석을 추가하면 다른 개발자들이 컴포넌트의 목적과 사용법을 이해하는 데 도움이 될 것입니다.

다음과 같이 개선해 보세요:

 @Composable
+/**
+ * 활동 이력 항목을 표시하는 컴포넌트
+ *
+ * @param modifier 컴포넌트에 적용할 수정자
+ * @param generation YAPP 기수
+ * @param position 포지션(직책)
+ * @param slot 추가 콘텐츠를 위한 선택적 슬롯
+ */
 internal fun HistoryItems(
     modifier: Modifier = Modifier,
     generation: Int,
     position: String,
     slot: @Composable (() -> Unit)? = null
 ) {
     Column(modifier = modifier.fillMaxWidth()) {
         Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
             Text(modifier = Modifier.weight(1f), text = position, style = YappTheme.typography.heading2Bold)
-            Image(painter = painterResource(coreDesignR.drawable.icon_yapp), contentDescription = null)
+            Image(painter = painterResource(coreDesignR.drawable.icon_yapp), contentDescription = "YAPP 로고")
             Text("${generation}기", style = YappTheme.typography.label1NormalMedium)
         }

         slot?.invoke()
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
@Composable
internal fun HistoryItems(
modifier: Modifier = Modifier,
generation: Int,
position: String,
slot: @Composable (() -> Unit)? = null
) {
Column(modifier = modifier.fillMaxWidth()) {
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
Text(modifier = Modifier.weight(1f), text = position, style = YappTheme.typography.heading2Bold)
Image(painter = painterResource(coreDesignR.drawable.icon_yapp), contentDescription = null)
Text("${generation}", style = YappTheme.typography.label1NormalMedium)
}
slot?.invoke()
}
}
@Composable
/**
* 활동 이력 항목을 표시하는 컴포넌트
*
* @param modifier 컴포넌트에 적용할 수정자
* @param generation YAPP 기수
* @param position 포지션(직책)
* @param slot 추가 콘텐츠를 위한 선택적 슬롯
*/
internal fun HistoryItems(
modifier: Modifier = Modifier,
generation: Int,
position: String,
slot: @Composable (() -> Unit)? = null
) {
Column(modifier = modifier.fillMaxWidth()) {
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
Text(
modifier = Modifier.weight(1f),
text = position,
style = YappTheme.typography.heading2Bold
)
Image(
painter = painterResource(coreDesignR.drawable.icon_yapp),
contentDescription = "YAPP 로고"
)
Text(
text = "${generation}",
style = YappTheme.typography.label1NormalMedium
)
}
slot?.invoke()
}
}

Comment on lines 78 to +84
ProfileIntent.OnLaunchedLogout -> {

viewModelScope.launch {
logoutUseCase().onSuccess {
sideEffect(ProfileSideEffect.NavigateToLogin)
}
}
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

로그아웃 처리 구현 검토

로그아웃 기능이 잘 구현되어 있습니다. 다만 에러 처리가 없는 것이 주의됩니다. 로그아웃 실패 시 사용자에게 알림을 주는 로직을 추가하는 것이 좋을 것 같습니다.

 ProfileIntent.OnLaunchedLogout -> {
     viewModelScope.launch {
-        logoutUseCase().onSuccess {
-            sideEffect(ProfileSideEffect.NavigateToLogin)
-        }
+        logoutUseCase()
+            .onSuccess {
+                sideEffect(ProfileSideEffect.NavigateToLogin)
+            }
+            .onFailure { error ->
+                error.record()
+                // 로그아웃 실패 처리 (예: 토스트 메시지 등)
+            }
     }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
ProfileIntent.OnLaunchedLogout -> {
viewModelScope.launch {
logoutUseCase().onSuccess {
sideEffect(ProfileSideEffect.NavigateToLogin)
}
}
}
ProfileIntent.OnLaunchedLogout -> {
viewModelScope.launch {
logoutUseCase()
.onSuccess {
sideEffect(ProfileSideEffect.NavigateToLogin)
}
.onFailure { error ->
error.record()
// 로그아웃 실패 처리 (예: 토스트 메시지 등)
}
}
}

}
PreviousHistoryIntent.OnEntryScreen -> {
previousHistoryUseCase.invoke()
.catch { it.record() }
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

오류 처리 향상을 고려해보세요.

현재 코드에서는 catch { it.record() }로 오류를 기록만 하고 있습니다. 사용자에게 오류 상태를 표시하는 로직이 없습니다. 오류가 발생했을 때 사용자에게 알려주는 UI 상태 업데이트나 사이드 이펙트를 추가하는 것을 고려해보세요.

-                previousHistoryUseCase.invoke()
-                    .catch { it.record() }
-                    .onEach { result ->
+                previousHistoryUseCase.invoke()
+                    .catch { error -> 
+                        error.record()
+                        reduce { copy(items = emptyList()) }
+                        sideEffect(PreviousHistorySideEffect.ShowError("데이터를 불러오는 중 오류가 발생했습니다."))
+                    }
+                    .onEach { result ->

이를 위해 PreviousHistorySideEffect에 아래와 같은 사이드 이펙트를 추가해야 합니다:

data class ShowError(val message: String) : PreviousHistorySideEffect

Comment on lines +75 to +79
HistoryItems(
modifier = Modifier.background(
color = YappTheme.colorScheme.orange99,
shape = RoundedCornerShape(12.dp)
).padding(16.dp),
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

Modifier 체이닝을 더 깔끔하게 할 수 있습니다.

현재 Modifier를 적용하는 방식에서 좀 더 가독성 있게 체이닝할 수 있습니다. 또한 하드코딩된 UI 값들(색상, 모서리 둥글기)을 테마 시스템 또는 상수로 추출하는 것을 고려해보세요.

 HistoryItems(
-    modifier = Modifier.background(
-        color = YappTheme.colorScheme.orange99,
-        shape = RoundedCornerShape(12.dp)
-    ).padding(16.dp),
+    modifier = Modifier
+        .background(
+            color = YappTheme.colorScheme.orange99,
+            shape = RoundedCornerShape(12.dp)
+        )
+        .padding(16.dp),
     position = item.position,
     generation = item.generation,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
HistoryItems(
modifier = Modifier.background(
color = YappTheme.colorScheme.orange99,
shape = RoundedCornerShape(12.dp)
).padding(16.dp),
HistoryItems(
modifier = Modifier
.background(
color = YappTheme.colorScheme.orange99,
shape = RoundedCornerShape(12.dp)
)
.padding(16.dp),
position = item.position,
generation = item.generation,

Comment on lines +83 to +85
if (item.activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()) {
Text("${item.activityStartDate} - ${item.activityEndDate}")
}
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

날짜 표시 형식을 개선하는 것이 좋겠습니다.

현재 날짜 표시 방식은 단순히 날짜 문자열을 "-"로 연결하고 있습니다. 가독성과 일관성을 위해 날짜 포맷팅을 적용하고, 텍스트 스타일을 지정하는 것이 좋습니다.

 if (item.activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()) {
-    Text("${item.activityStartDate} - ${item.activityEndDate}")
+    Text(
+        text = "${item.activityStartDate} - ${item.activityEndDate}",
+        style = YappTheme.typography.caption2Normal,
+        color = YappTheme.colorScheme.grayScale60
+    )
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (item.activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()) {
Text("${item.activityStartDate} - ${item.activityEndDate}")
}
if (item.activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()) {
Text(
text = "${item.activityStartDate} - ${item.activityEndDate}",
style = YappTheme.typography.caption2Normal,
color = YappTheme.colorScheme.grayScale60
)
}

Comment on lines +74 to +89
items(items) { item ->
HistoryItems(
modifier = Modifier.background(
color = YappTheme.colorScheme.orange99,
shape = RoundedCornerShape(12.dp)
).padding(16.dp),
position = item.position,
generation = item.generation,
slot = {
if (item.activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()) {
Text("${item.activityStartDate} - ${item.activityEndDate}")
}
}
)
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

로딩, 오류, 빈 상태 처리를 추가하는 것이 좋겠습니다.

현재 구현에서는 items가 비어있을 때의 UI 상태 처리가 없습니다. 데이터가 로딩 중이거나, 오류가 발생했거나, 데이터가 없을 때 사용자에게 적절한 피드백을 제공하는 UI를 추가하면 사용자 경험이 향상될 것입니다.

 LazyColumn(
     modifier = Modifier.weight(1f),
     contentPadding = PaddingValues(20.dp)
 ) {
+    if (items.isEmpty()) {
+        item {
+            Column(
+                modifier = Modifier.fillMaxSize(),
+                verticalArrangement = Arrangement.Center,
+                horizontalAlignment = Alignment.CenterHorizontally
+            ) {
+                Text(
+                    text = stringResource(R.string.no_history_data),
+                    style = YappTheme.typography.body1Normal,
+                    color = YappTheme.colorScheme.grayScale60
+                )
+            }
+        }
+    } else {
         items(items) { item ->
             HistoryItems(
                 modifier = Modifier.background(
                     color = YappTheme.colorScheme.orange99,
                     shape = RoundedCornerShape(12.dp)
                 ).padding(16.dp),
                 position = item.position,
                 generation = item.generation,
                 slot = {
                     if (item.activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()) {
                         Text("${item.activityStartDate} - ${item.activityEndDate}")
                     }
                 }
             )
         }
+    }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
items(items) { item ->
HistoryItems(
modifier = Modifier.background(
color = YappTheme.colorScheme.orange99,
shape = RoundedCornerShape(12.dp)
).padding(16.dp),
position = item.position,
generation = item.generation,
slot = {
if (item.activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()) {
Text("${item.activityStartDate} - ${item.activityEndDate}")
}
}
)
}
}
LazyColumn(
modifier = Modifier.weight(1f),
contentPadding = PaddingValues(20.dp)
) {
if (items.isEmpty()) {
item {
Column(
modifier = Modifier.fillMaxSize(),
verticalArrangement = Arrangement.Center,
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = stringResource(R.string.no_history_data),
style = YappTheme.typography.body1Normal,
color = YappTheme.colorScheme.grayScale60
)
}
}
} else {
items(items) { item ->
HistoryItems(
modifier = Modifier
.background(
color = YappTheme.colorScheme.orange99,
shape = RoundedCornerShape(12.dp)
)
.padding(16.dp),
position = item.position,
generation = item.generation,
slot = {
if (item.activityEndDate.orEmpty().isNotEmpty()
&& item.activityStartDate.orEmpty().isNotEmpty()
) {
Text("${item.activityStartDate} - ${item.activityEndDate}")
}
}
)
}
}
}

@@ -1,19 +1,20 @@
package com.yapp.feature.profile.component

import androidx.compose.foundation.Image
Copy link

Choose a reason for hiding this comment

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

🧹 Nitpick (assertive)

프로필 이미지 UI 개선, 접근성 개선 필요.

빈 Box 대신 실제 프로필 이미지를 표시하도록 변경한 것은 좋은 개선입니다. 그러나 contentDescription이 null로 설정되어 있어 접근성 지원이 제한될 수 있습니다.

다음과 같이 의미 있는 contentDescription을 추가하는 것이 좋습니다:

- Image(painter = painterResource(coreDesignR.drawable.yappo_profile), contentDescription = null)
+ Image(painter = painterResource(coreDesignR.drawable.yappo_profile), contentDescription = "사용자 프로필 이미지")

Also applies to: 12-12, 17-17, 32-32

suspend fun getUserAccessToken() : Flow<String>
suspend fun deleteAccount()
suspend fun getUserProfile(): Flow<UserInfo>
fun getUserActivityHistories(): Flow<ActivityHistory>
Copy link
Member

Choose a reason for hiding this comment

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

C: 저희 저번에 꼭 필요한 경우에만 Flow를 사용하기로 했던 것 같아요.

navigateToBack: () -> Unit
) {
composable<PreviousHistory> {
PreviousHistoryRoute(onClickBackButton = navigateToBack)
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
PreviousHistoryRoute(onClickBackButton = navigateToBack)
PreviousHistoryRoute(navigateToBack = navigateToBack)

A: 기존 네이밍 컨벤션 맞춰주시면 좋을 것 같아요

Comment on lines +19 to +20
data object OnEntryScreen : PreviousHistoryIntent
data object OnClickBackButton : PreviousHistoryIntent
Copy link
Member

Choose a reason for hiding this comment

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

A: 여기도 컨벤션 맞춰주시면 좋을 것 같습니다.

modifier = Modifier.weight(1f),
contentPadding = PaddingValues(20.dp)
) {
items(items) { item ->
Copy link
Member

Choose a reason for hiding this comment

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

A: key로 지정할게 딱히 없었나용?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

음 아니요 아이템 자체가 그렇게 많지 않을거라 생각해서 따로 key 는 지정하지 않았습니다

Comment on lines +25 to +26
import com.yapp.feature.history.previous.PreviousHistoryIntent as Intent
import com.yapp.feature.history.previous.PreviousHistorySideEffect as SideEffect
Copy link
Member

Choose a reason for hiding this comment

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

이거 좋네요 👍

position = item.position,
generation = item.generation,
slot = {
if (item.activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()) {
Copy link
Member

Choose a reason for hiding this comment

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

A: 이건 data class에서 처리하는게 어떨까요?

val showSlot = activityEndDate.orEmpty().isNotEmpty() && item.activityStartDate.orEmpty().isNotEmpty()

Comment on lines +7 to +22
internal class PreviousHistoryUseCase @Inject constructor(
private val userRepository: UserRepository
){
operator fun invoke() = userRepository.getUserActivityHistories().map { result ->
PreviousHistoryState(
items = result.activityUnits.map { unit ->
PreviousHistoryState.History(
generation = unit.generation,
position = unit.position,
activityStartDate = unit.activityStartDate,
activityEndDate = unit.activityEndDate
)
}
)
}
}
Copy link
Member

Choose a reason for hiding this comment

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

R: UseCase는 도메인 모듈에 만들어주세요

Copy link
Contributor Author

Choose a reason for hiding this comment

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

이거 같은 경우는 타입 변경하는 처리를 위해 유즈케이스 라는
네이밍을 가진 클래스를 만들었습니다

마땅한 네이밍을 정하지 못해 유즈케이스로 정하기도 했었어요

Comment on lines 97 to 102
onClickSettings = { viewModel.store.onIntent(ProfileIntent.OnClickSettings) },
onClickPreviousHistory = {},
onClickPreviousHistory = { viewModel.store.onIntent(ProfileIntent.OnClickPreviousHistory) },
onClickAttendHistory = { viewModel.store.onIntent(ProfileIntent.OnClickAttendHistory) },
onClickQuestion = {},
onClickWithdraw = {},
onClickQuestion = { viewModel.store.onIntent(ProfileIntent.OnClickUsage) },
onClickWithdraw = { viewModel.store.onIntent(ProfileIntent.OnClickWithdraw) },
onCLickLogout = { viewModel.store.onIntent(ProfileIntent.OnClickLogout) }
Copy link
Member

Choose a reason for hiding this comment

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

R: Screen에서는 onIntent만 넣어주세요
https://github.com/YAPP-admin/yappu-world-android/blob/develop/feature/notice/src/main/java/com/yapp/feature/notice/notice/NoticeRoute.kt

다른 Screen에도 컨벤션 맞춰주시면 감사하겠습니다.

Copy link
Member

Choose a reason for hiding this comment

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

R:

HorizontalDivider(thickness = 12.dp, color = YappTheme.colorScheme.lineNormalNormal.copy(alpha = 0.08f))

피그마 디자인과 색상이 맞지 않아 위와 같이 반영해주시면 감사하겠습니다.

Copy link
Member

@DongChyeon DongChyeon left a comment

Choose a reason for hiding this comment

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

고생하셨습니다. 몇가지 리뷰 사항 확인해주세요.
브랜치명도 컨벤션 맞춰서 feature/#137-mypage-detail 로 바꿔주시면 좋을 거 같아요

Comment on lines 24 to +29
override suspend fun getUserProfile() = flow<UserInfo> { emit(userApi.getUserProfile().toModel())}
} No newline at end of file
override fun getUserActivityHistories() = flow {
emit(userApi.getUserActivityHistories().toModel())
}
}
Copy link
Member

@DongChyeon DongChyeon Apr 26, 2025

Choose a reason for hiding this comment

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

A:

override suspend fun getUserProfile(): Flow<UserInfo> = flow {  
    emit(userApi.getUserProfile().toModel())
}

override fun getUserActivityHistories(): Flow<ActivityHistory> = flow {
    emit(userApi.getUserActivityHistories().toModel())
}

요것두 기능상 아무 문제 없지만 코드 스타일 통일하면 좋을 것 같아요.

Comment on lines 22 to +26
data object OnCancelLogout : ProfileIntent
data object OnDismissLogout : ProfileIntent
data object OnLaunchedLogout : ProfileIntent
data object OnLaunchedWithdraw : ProfileIntent
data object OnCancelWithdraw : ProfileIntent
Copy link
Member

Choose a reason for hiding this comment

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

A:
해당 리뷰 처럼 Intent 컨벤션 맞춰주시면 감사하겠습니다.

Comment on lines 97 to 102
onClickSettings = { viewModel.store.onIntent(ProfileIntent.OnClickSettings) },
onClickPreviousHistory = {},
onClickPreviousHistory = { viewModel.store.onIntent(ProfileIntent.OnClickPreviousHistory) },
onClickAttendHistory = { viewModel.store.onIntent(ProfileIntent.OnClickAttendHistory) },
onClickQuestion = {},
onClickWithdraw = {},
onClickQuestion = { viewModel.store.onIntent(ProfileIntent.OnClickUsage) },
onClickWithdraw = { viewModel.store.onIntent(ProfileIntent.OnClickWithdraw) },
onCLickLogout = { viewModel.store.onIntent(ProfileIntent.OnClickLogout) }
Copy link
Member

Choose a reason for hiding this comment

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

R:

HorizontalDivider(thickness = 12.dp, color = YappTheme.colorScheme.lineNormalNormal.copy(alpha = 0.08f))

피그마 디자인과 색상이 맞지 않아 위와 같이 반영해주시면 감사하겠습니다.

Comment on lines +21 to +37
@Composable
internal fun HistoryItems(
modifier: Modifier = Modifier,
generation: Int,
position: String,
slot: @Composable (() -> Unit)? = null
) {
Column(modifier = modifier.fillMaxWidth()) {
Row(horizontalArrangement = Arrangement.spacedBy(12.dp), verticalAlignment = Alignment.CenterVertically) {
Text(modifier = Modifier.weight(1f), text = position, style = YappTheme.typography.heading2Bold)
Image(painter = painterResource(coreDesignR.drawable.icon_yapp), contentDescription = null)
Text("${generation}기", style = YappTheme.typography.label1NormalMedium)
}

slot?.invoke()
}
}
Copy link
Member

@DongChyeon DongChyeon Apr 26, 2025

Choose a reason for hiding this comment

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

R:

@Composable
internal fun HistoryItems(
    modifier: Modifier = Modifier,
    generation: Int,
    position: String,
    slot: @Composable (() -> Unit)? = null
) {
    Column(modifier = modifier.fillMaxWidth()) {
        Row(
            horizontalArrangement = Arrangement.spacedBy(2.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                modifier = Modifier.weight(1f),
                text = position,
                style = YappTheme.typography.heading2Bold
            )
            Box(
                modifier = Modifier.size(20.dp),
                contentAlignment = Alignment.Center
            ) {
                Image(
                    modifier = Modifier.size(16.dp),
                    painter = painterResource(coreDesignR.drawable.icon_yapp),
                    contentDescription = null
                )
            }
            Text(
                "${generation}",
                style = YappTheme.typography.label1NormalMedium
            )
        }

        slot?.invoke()
    }
}

피그마 디자인에 맞춰 아이콘 크기 및 간격이 수정이 필요해보입니다.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

넵 이거 확인해보니 Column 에도 수직 간격이 달라서 그것도 수정했습니다

Copy link
Member

Choose a reason for hiding this comment

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

R:
피그마 디자인 보면은 배경색상을 staticWhite로 쓰셔야할 것 같아요

Copy link
Member

Choose a reason for hiding this comment

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

C:

LaunchedEffect(viewModel.store.sideEffects) {
    viewModel.store.sideEffects.onEach { effect ->
        when (effect) {
            SideEffect.NavigateToSetting -> {
                onNavigateToSettings()
            }
            SideEffect.NavigateToAttendHistory -> {
                onNavigateToAttendHistory()
            }
            SideEffect.NavigateToPreviousHistory -> {
                onNavigateToPreviousHistory()
            }
            SideEffect.NavigateToLogin -> {
                onNavigateToLogin()
            }
            SideEffect.NavigateToUsage -> {

            }
        }
    }.launchIn(scope)
}
viewModel.store.sideEffects.collectWithLifecycle { effect ->
    when (effect) {
        SideEffect.Finish -> {
            onClickBackButton()
        }
    }
}

collectWithLifeCycle을 composable 본문에 두면 해당 이슈 가 발생하는데
여태까지의 sideEffect 수집이 다 두번째 방안처럼 이루어져있었어서 성능상은 첫번째가 맞는 것 같아 논의가 필요할 거 같아요

@jinukeu

Copy link
Member

@jinukeu jinukeu Apr 26, 2025

Choose a reason for hiding this comment

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

@Composable
inline fun <reified T> Flow<T>.collectWithLifecycle(
    minActiveState: Lifecycle.State = Lifecycle.State.STARTED,
    noinline action: suspend (T) -> Unit,
) {
    val lifecycleOwner = LocalLifecycleOwner.current
    LaunchedEffect(this, lifecycleOwner) {
        lifecycleOwner.lifecycle.repeatOnLifecycle(minActiveState) {
            this@collectWithLifecycle.collect { action(it) }
        }
    }
}

collectWithLifecycle 내부 구현체인데용 보시면 안에 LaunchedEffect로 되어있어서 성능상 이슈는 없을거에요
코드 래빗이 실수한 것 같습니다. @DongChyeon

(패키지 위치 : package com.yapp.core.ui.extension)

Copy link
Member

Choose a reason for hiding this comment

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

그리고 태성님이 하신 방법대로 하면 ... 앱이 백그라운드로 내려가도 계속 collect를 하고 있기 때문에 성능상 안좋을 것 같아요 (repeatOnLifecycle이 없네요 ~) @TaeseongYun @DongChyeon

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

와 이건 생각하지 못했던 부분이네요 덕분에 하나 알아갔습니다

@TaeseongYun TaeseongYun deleted the feature#137-mypage-detail branch April 27, 2025 05:45
@TaeseongYun TaeseongYun restored the feature#137-mypage-detail branch April 27, 2025 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CodeRabbit CodeRabbit 코드 리뷰 요청 Feature 기능 추가, 개발

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants