Skip to content

fix: 통증 부위 선택 오류 수정 #204

Merged
taekoong merged 2 commits intomainfrom
fe/feat/pain-record
Aug 28, 2025
Merged

fix: 통증 부위 선택 오류 수정 #204
taekoong merged 2 commits intomainfrom
fe/feat/pain-record

Conversation

@taekoong
Copy link
Collaborator

@taekoong taekoong commented Aug 28, 2025

Important

Fixes body part selection for abdomen, waist, hip, and pelvis in HealthStatusInputScreen and updates related display logic.

  • Behavior:
    • Fixes body part selection for abdomen, waist, hip, and pelvis in _HealthStatusInputScreenState.
    • Updates _updateBodyPartsFromRecords() to reset abdomen-related states.
    • Modifies _updateBodyPartsDisplay() to handle abdomen, waist, hip, and pelvis based on view.
    • Adjusts onBodyPartsSelected() to update selection states for abdomen-related parts.
  • Misc:
    • Changes '배' to '복부' in getStretchingLinks().
    • Removes debug print statements in _buildTitleText() and other places.

This description was created by Ellipsis for 1aafd7a. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • 신기능
    • 복부 관련 세부 부위 선택(복부/허리/엉덩이/골반) 지원.
    • 전면/후면 보기별 선택 표시 로직 개선으로 시각적 일관성 향상.
    • 선택 여부 감지 강화로 통증 부위 수집 정확도 개선.
  • 버그 수정
    • 입력 중 기록 동기화로 선택이 덮어쓰이던 문제 방지.
    • 기록에서 불러온 통증 부위가 화면에 일관되게 반영되도록 개선.
  • 스타일/현지화
    • ‘배’를 ‘복부’로 용어 통일, 관련 라벨·스트레칭 링크 업데이트.

@coderabbitai
Copy link

coderabbitai bot commented Aug 28, 2025

Walkthrough

건강 상태 입력 화면에서 복부 관련 선택 상태를 네 가지(복부/허리/엉덩이/골반)로 세분화하고, 기록 동기화·표시·선택 로직을 이에 맞게 전면 수정했습니다. 입력 모드 여부에 따라 기록 반영을 제어하며, 한국어 라벨을 복부(복부/허리/골반/엉덩이)로 통일했습니다.

Changes

Cohort / File(s) Change Summary
상태 관리 세분화
frontend/ongi/lib/screens/health/health_status_input_screen.dart
복부 영역을 네 개의 불리언 상태로 분리: _abdomenSelected, _waistSelected, _hipSelected, _pelvisSelected 추가 및 내부 BodyParts 상태와의 연동 방식 변경
기록 동기화 로직
frontend/ongi/lib/screens/health/health_status_input_screen.dart
_loadPainRecords가 입력 모드가 아닐 때만 기록으로 상태를 갱신하도록 변경; _updateBodyPartsFromRecords 추가하여 기록 기반 초기화/리셋 처리
표시(Front/Back) 매핑
frontend/ongi/lib/screens/health/health_status_input_screen.dart
_updateBodyPartsDisplay에서 전/후면별 매핑 갱신: Front(하체→복부, abdomen→골반, vestibular→엉덩이), Back(하체→허리, abdomen→엉덩이, vestibular→골반)
선택/수집 로직
frontend/ongi/lib/screens/health/health_status_input_screen.dart
_getSelectedPainAreas를 네 불리언 기반으로 재구성; onBodyPartsSelected가 복합 BodyParts를 디코드해 네 불리언으로 반영하고 표시 갱신; hasSelectedParts에 네 불리언 포함
로컬라이제이션/라벨
frontend/ongi/lib/screens/health/health_status_input_screen.dart
한국어 매핑에서 abdomen을 ‘배’→‘복부’로 변경, 스트레칭 링크·라벨 키 업데이트
기타 정리
frontend/ongi/lib/screens/health/health_status_input_screen.dart
디버그 출력 정리 및 새 추상화에 맞춘 메시지 조정; 퍼블릭 API 시그니처 변경 없음

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as 사용자
  participant Screen as HealthStatusInputScreen
  participant Records as PainRecordsStore

  User->>Screen: 화면 진입
  Screen->>Records: _loadPainRecords()
  alt 입력 모드 아님
    Records-->>Screen: 기록 목록
    Screen->>Screen: _updateBodyPartsFromRecords()\n- 네 불리언 리셋/적용\n- 자식 위젯 읽기 전용 설정
    Screen->>Screen: _updateBodyPartsDisplay(isFront)
  else 입력 모드
    Records-->>Screen: 기록 무시(상태 유지)
  end

  User->>Screen: 신체부위 선택(onBodyPartsSelected)
  Screen->>Screen: BodyParts → 네 불리언 디코드
  Screen->>Screen: _updateBodyPartsDisplay(isFront)
  Screen->>Screen: _getSelectedPainAreas() 수집
  note right of Screen: hasSelectedParts 확인
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Poem

토끼는 뽁뽁, 복부를 콕콕,
허리와 골반, 엉덩이도 톡톡.
앞면이면 이렇게, 뒷면이면 저렇게—똑딱!
기록은 잠깐, 입력 땐 살짝 멈칫.
오늘의 통증 지도, 깔끔히 업데이트! 🗺️🐇

Tip

🔌 Remote MCP (Model Context Protocol) integration is now available!

Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats.

✨ Finishing Touches
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fe/feat/pain-record

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:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbit in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbit 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:
    • @coderabbit gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbit read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbit help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbit ignore or @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbit summary or @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbit or @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

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • 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.

Copy link

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

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

Important

Looks good to me! 👍

Reviewed everything up to 1aafd7a in 1 minute and 20 seconds. Click for details.
  • Reviewed 240 lines of code in 1 files
  • Skipped 0 files when reviewing.
  • Skipped posting 6 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. frontend/ongi/lib/screens/health/health_status_input_screen.dart:37
  • Draft comment:
    New boolean state variables for abdomen, waist, hip, and pelvis have been added. Consider adding a brief inline comment explaining their distinct roles in relation to the BodyParts model.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
2. frontend/ongi/lib/screens/health/health_status_input_screen.dart:306
  • Draft comment:
    In _updateBodyPartsFromRecords, pain area cases now update dedicated booleans (e.g. _abdomenSelected) instead of directly modifying the BodyParts via copyWith. Ensure this design choice is consistent across the state management.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
3. frontend/ongi/lib/screens/health/health_status_input_screen.dart:369
  • Draft comment:
    The mapping for pelvis and hip in _updateBodyPartsDisplay is reversed between front and back views. Please ensure that this reversed mapping is intentional and add a clarifying comment if needed.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
4. frontend/ongi/lib/screens/health/health_status_input_screen.dart:828
  • Draft comment:
    In onBodyPartsSelected, lower body selection is mapped to _abdomenSelected (front view) and to _waistSelected (back view) while pelvis and hip are updated according to the view. Verify that these mappings conform to the intended UI behavior.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None
5. frontend/ongi/lib/screens/health/health_status_input_screen.dart:438
  • Draft comment:
    Changed the stretching link label from '배' to '복부' for consistency with updated terminology. This looks correct.
  • Reason this comment was not posted:
    Confidence changes required: 0% <= threshold 50% None
6. frontend/ongi/lib/screens/health/health_status_input_screen.dart:357
  • Draft comment:
    Multiple sequential calls to _bodyParts.copyWith in _updateBodyPartsDisplay could be consolidated into a single call to improve readability and possibly performance.
  • Reason this comment was not posted:
    Confidence changes required: 33% <= threshold 50% None

Workflow ID: wflow_311mLjiDTbqlZhSK

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

@taekoong taekoong merged commit 6b9ed28 into main Aug 28, 2025
3 of 4 checks passed
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: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
frontend/ongi/lib/screens/health/health_status_input_screen.dart (2)

815-861: BodyParts.toString 파싱 의존 제거

toString() 문자열 검색은 라이브러리 변경에 취약합니다. BodyParts의 공개 필드를 직접 참조하는 방식으로 교체하세요.

-    final partsString = parts.toString();
-    // 가슴/등 선택 상태 업데이트 (앞/뒤 구분)
-    final upperBodySelected = partsString.contains('upperBody: true');
+    // 가슴/등 선택 상태 업데이트 (앞/뒤 구분)
+    final upperBodySelected = parts.upperBody;

-    // 복부 부위 선택 상태 업데이트
-    final lowerBodySelected = partsString.contains('lowerBody: true');
-    final abdomenSelected = partsString.contains('abdomen: true');
-    final vestibularSelected = partsString.contains('vestibular: true');
+    // 복부 부위 선택 상태 업데이트
+    final lowerBodySelected   = parts.lowerBody;
+    final abdomenSelected     = parts.abdomen;
+    final vestibularSelected  = parts.vestibular;

필드 직접 접근이 불가능한 타입이라면, 안전한 파서/헬퍼를 도입해 문자열 의존을 캡슐화하세요.


1475-1481: Color.withValues 사용은 빌드 실패 위험

Flutter 안정 채널에서는 withOpacity가 표준입니다. withValues가 미지원이면 컴파일 에러가 납니다. 호환성 위해 교체를 권장합니다.

- color: Colors.black.withValues(
-   alpha: 0.1,
- ),
+ color: Colors.black.withOpacity(0.1),

동일 패턴을 두 블록 모두에 적용해 주세요.

Also applies to: 1517-1520

🧹 Nitpick comments (3)
frontend/ongi/lib/screens/health/health_status_input_screen.dart (3)

253-268: 디버그 로그 가드 처리 필요

print가 다수 남아 있습니다. 출시 빌드에서 불필요한 콘솔 출력/성능 저하를 막기 위해 kDebugMode 가드를 권장합니다.

예시 패치(동일 패턴을 본 블록 전반에 적용):

+import 'package:flutter/foundation.dart';
...
- print('디버깅 - 원본 painArea: $painArea (타입: ${painArea.runtimeType})');
+ if (kDebugMode) debugPrint('디버그: 원본 painArea: $painArea (${painArea.runtimeType})');

- print('디버깅 - 처리할 areas: $areas');
+ if (kDebugMode) debugPrint('디버그: 처리할 areas: $areas');

- print('디버깅 - 처리 중인 부위: $areaUpper');
+ if (kDebugMode) debugPrint('디버그: 처리 중인 부위: $areaUpper');

354-381: copyWith 연속 호출을 단일 호출로 합쳐 재빌드 비용 축소

동일 setState 내에서 _bodyParts를 4회 재할당합니다. 한 번에 묶어 객체 생성/디프를 줄이는 편이 좋습니다.

   void _updateBodyPartsDisplay() {
     setState(() {
-      if (isFrontView) {
-        _bodyParts = _bodyParts.copyWith(upperBody: _chestSelected);
-        _bodyParts = _bodyParts.copyWith(lowerBody: _abdomenSelected);
-      } else {
-        _bodyParts = _bodyParts.copyWith(upperBody: _backSelected);
-        _bodyParts = _bodyParts.copyWith(lowerBody: _waistSelected);
-      }
-
-      if (isFrontView) {
-        _bodyParts = _bodyParts.copyWith(abdomen: _pelvisSelected);
-        _bodyParts = _bodyParts.copyWith(vestibular: _hipSelected);
-      } else {
-        _bodyParts = _bodyParts.copyWith(abdomen: _hipSelected);
-        _bodyParts = _bodyParts.copyWith(vestibular: _pelvisSelected);
-      }
+      _bodyParts = _bodyParts.copyWith(
+        upperBody: isFrontView ? _chestSelected : _backSelected,
+        lowerBody: isFrontView ? _abdomenSelected : _waistSelected,
+        abdomen:   isFrontView ? _pelvisSelected : _hipSelected,
+        vestibular:isFrontView ? _hipSelected    : _pelvisSelected,
+      );
     });
   }

623-629: 스낵바 ‘복사’ 액션 동작 추가 제안

현재 TODO 상태입니다. 실제 복사 동작과 피드백을 추가하세요.

+import 'package:flutter/services.dart';
...
-                                            onPressed: () {
-                                              // URL을 클립보드에 복사하는 기능 추가 가능
-                                            },
+                                            onPressed: () async {
+                                              await Clipboard.setData(ClipboardData(text: url));
+                                              if (context.mounted) {
+                                                ScaffoldMessenger.of(context).showSnackBar(
+                                                  const SnackBar(
+                                                    content: Text('링크가 클립보드에 복사되었습니다.'),
+                                                    duration: Duration(seconds: 2),
+                                                  ),
+                                                );
+                                              }
+                                            },
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 526ba42 and 1aafd7a.

📒 Files selected for processing (1)
  • frontend/ongi/lib/screens/health/health_status_input_screen.dart (12 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
frontend/ongi/lib/screens/health/health_status_input_screen.dart (1)
backend/ongi/src/main/java/ongi/health/entity/PainRecord.java (1)
  • PainArea (31-64)
🔇 Additional comments (5)
frontend/ongi/lib/screens/health/health_status_input_screen.dart (5)

37-41: 복부/허리/엉덩이/골반 상태 분리, 방향성 좋습니다

선택 오동작을 분해해 해결한 접근이 타당합니다. 이후 리셋/표시/저장 경로에 일관되게 반영된 점도 확인했습니다.


217-250: 조회 모드 진입 시 상태 리셋 로직 명확

기록 없음/있음에 따라 입력 모드·스트레칭 노출·내부 선택 상태를 일관되게 초기화하는 흐름이 깔끔합니다.


306-317: 기록 → 내부 상태 매핑 적절

ABDOMEN/WAIST/PELVIS/HIP를 전용 bool로 분리해 반영하는 로직이 명확합니다.


979-986: 용어 통일(배 → 복부) 확인

한글 라벨을 ‘복부’로 통일한 매핑이 백엔드 enum(ABDOMEN)과도 일치합니다.


194-197: 백엔드 record['date'] 필드 포맷/타임존 일관성 확인 필요
클라이언트는 selectedDateDateFormat('yyyy-MM-dd')(로컬 타임존)로 포맷해 record['date'] 문자열과 비교하고 있습니다. 스크립트 점검 결과 해당 포맷이 여러 곳에서 일관되게 사용되나, 백엔드가 UTC 기준으로 날짜를 저장·반환한다면 off-by-one 이슈가 발생할 수 있습니다.
API 스펙에서 date 필드가 로컬/UTC 중 어느 기준인지 확인하고, 필요 시 DateTime으로 파싱 후 로컬 타임존으로 정규화하여 비교 로직을 재검토하세요.

Comment on lines +200 to +203
// 입력 모드가 아닐 때만 기록에서 신체 부위 업데이트
if (!_isInputMode) {
_updateBodyPartsFromRecords();
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

날짜 변경 시 입력 모드 유지로 인해 기록 UI 미갱신 가능성

입력 모드(true) 상태에서 날짜를 바꾸면 _loadPainRecords_updateBodyPartsFromRecords()를 건너뜁니다. 해당 날짜에 기록이 있어도 화면에 반영되지 않아 혼란을 줄 수 있습니다. 날짜 변경 시 조회 모드로 내려 UI를 기록 기반으로 재구성하는 것이 안전합니다.

다음과 같이 날짜 변경 시 입력 모드를 해제하는 편이 명확합니다.

   void _onDateChanged(DateTime newDate) {
-    setState(() {
-      selectedDate = newDate;
-    });
+    setState(() {
+      selectedDate = newDate;
+      _isInputMode = false; // 날짜 변경 → 우선 조회 모드로 전환
+    });
     _loadPainRecords();
   }
📝 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 (!_isInputMode) {
_updateBodyPartsFromRecords();
}
void _onDateChanged(DateTime newDate) {
setState(() {
selectedDate = newDate;
_isInputMode = false; // 날짜 변경 → 우선 조회 모드로 전환
});
_loadPainRecords();
}
🤖 Prompt for AI Agents
In frontend/ongi/lib/screens/health/health_status_input_screen.dart around lines
200 to 203, changing the date while _isInputMode is true skips calling
_updateBodyPartsFromRecords(), leaving the UI out of sync; fix by forcing exit
from input mode when the date changes (set _isInputMode = false) before loading
records so _loadPainRecords will call _updateBodyPartsFromRecords(); make this
change inside the date-change handler and wrap the state change in setState (or
the equivalent state update) so the UI is rebuilt from records for the newly
selected date.

Comment on lines 868 to 875
return _bodyParts.toString().contains('true') ||
_chestSelected ||
_backSelected;
_backSelected ||
_abdomenSelected ||
_waistSelected ||
_hipSelected ||
_pelvisSelected;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

hasSelectedParts 계산 간소화

중복 로직과 toString() 의존을 피하기 위해 최종 산출 함수를 재사용하세요.

-  bool get hasSelectedParts {
-    return _bodyParts.toString().contains('true') ||
-        _chestSelected ||
-        _backSelected ||
-        _abdomenSelected ||
-        _waistSelected ||
-        _hipSelected ||
-        _pelvisSelected;
-  }
+  bool get hasSelectedParts => _getSelectedPainAreas().isNotEmpty;
🤖 Prompt for AI Agents
In frontend/ongi/lib/screens/health/health_status_input_screen.dart around lines
868-875, the current hasSelectedParts check relies on
_bodyParts.toString().contains('true') and duplicates logic; replace this with a
single reusable predicate (or call the existing final-output function) that
returns whether any body part is selected by evaluating
_bodyParts.values.any((v) => v) || _chestSelected || _backSelected ||
_abdomenSelected || _waistSelected || _hipSelected || _pelvisSelected, and use
that helper everywhere instead of the toString() check to eliminate duplication
and brittleness.

Neibce pushed a commit to 2025-PNU-SW-Hackathon/PNUSW-2025-OnGi-10 that referenced this pull request Aug 28, 2025
* feat: 통증 기록 부위 구현

* fix: 통증 부위 선택 오류 수정

---------

Co-authored-by: itaegyeong <taekoong@pusan.ac.kr>
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.

1 participant