Skip to content

Conversation

@KingSeokJin
Copy link
Collaborator

@KingSeokJin KingSeokJin commented Nov 22, 2025

📝 작업 내용

  • 바텀시트 템플릿 구현
  • 저장한 매장 버튼 구현
  • 저장한 매장 버튼 클릭시 바텀시트 등장 및 컨텐츠 구현
  • 그룹 만들기 로직 구현

📢 PR Point

  • 바텀시트 템플릿 동작 테스트를 위해 Router에 새롭게 example 페이지를 등록했습니다.

이미지 첨부

PR.mp4

🔧 다음 할 일

  • 저장한 매장 마커 변경하기
  • 클릭된 클러스터 마커 이미지 변경
  • 클러스터 클릭시 바텀시트 등장하도록 구현
  • 클러스터 클릭시 등장하는 바텀시트에 들어갈 페이지 구현
  • 내가 저장한 그룹 클릭시 해당 그룹에 포함된 식당 리스트 뜨도록 구현

Summary by CodeRabbit

  • 새로운 기능

    • 드래그 가능한 하단 시트(Bottom Sheet) 컴포넌트 및 예제 페이지 2개 추가
    • 그룹 목록 보기와 그룹 생성/편집 워크플로우(아이콘 선택 그리드, 이름 입력, 공개/비공개) 및 확인 모달 추가
    • 지도 화면에 하단 시트 연동, 상단 검색/액션 버튼 추가
    • 그룹 항목 행 컴포넌트와 토글 스위치 UI 추가
  • 의존성

    • 애니메이션 라이브러리(frаmer-motion) 추가

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Nov 22, 2025

Walkthrough

Framer Motion 기반 바텀시트, 모달, 토글 컴포넌트와 그룹 관리 UI를 추가하고, 전체 화면 CorkageMap 레이아웃 및 두 개의 예제 페이지와 라우트를 도입했으며 framer-motion 의존성을 패키지에 추가했습니다.

Changes

응집도 / 파일(s) 변경 요약
의존성 추가
package.json
런타임 의존성 framer-motion^12.23.24로 추가
공유 컴포넌트: BottomSheet
src/shared/components/bottomsheet/BottomSheet.tsx
드래그 가능 바텀시트 구현(스냅 포인트, 속도 기반 핸들링, overlay opacity, 반응형 재계산), export default BottomSheet
예제 페이지
src/pages/ExamplePage.tsx, src/pages/ExamplePage2.tsx
두 개의 바텀시트 데모 페이지 추가(드래그/스냅, 열기 버튼, 콘텐츠 슬롯)
라우터 업데이트
src/shared/router/Router.tsx
/example, /example2 경로 및 해당 페이지 임포트 추가
CorkageMap 레이아웃 및 통합
src/pages/corkagemap/CorkageMap.tsx
전체 화면 지도 레이아웃 재구성, 상단 바/액션 버튼 추가, BottomSheet 열기 상태(isSheetOpen, isActive) 통합
그룹 관리 목록 관련 파일
src/pages/corkagemap/list/List.tsx, src/pages/corkagemap/list/EditGroup.tsx, src/pages/corkagemap/list/ConfirmationModal.tsx
그룹 리스트/편집 워크플로우 추가: 생성/편집 뷰 전환, 저장 후 확인 모달 표시, EditGroup(이름 입력, 아이콘 선택, privacy), ConfirmationModal(애니메이션 모달)
보조 UI 컴포넌트
src/pages/corkagemap/list/MyGroup.tsx, src/pages/corkagemap/list/ToggleSwitch.tsx
MyGroup(그룹 행 렌더링) 및 ToggleSwitch(Framer Motion 기반 스위치) 추가

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Router
    participant ExamplePage
    participant CorkageMap
    participant BottomSheet
    participant List
    participant EditGroup
    participant ConfirmationModal

    User->>Router: /example 또는 /example2 요청
    Router->>ExamplePage: 페이지 렌더
    User->>CorkageMap: 우측 버튼 클릭 (목록 열기)
    CorkageMap->>BottomSheet: isOpen=true
    BottomSheet->>List: List 렌더링

    User->>List: "새 그룹" 클릭
    List->>EditGroup: edit 뷰로 전환
    User->>EditGroup: 데이터 입력 후 저장
    EditGroup->>List: onSave({name, iconName, privacy})
    List->>List: myGroups 업데이트
    List->>ConfirmationModal: showConfirmModal=true
    User->>ConfirmationModal: 닫기 클릭
    ConfirmationModal->>List: onClose()
    List->>BottomSheet: 목록 갱신
    User->>BottomSheet: 드래그/백드롭 클릭
    BottomSheet->>CorkageMap: onClose()
Loading
sequenceDiagram
    participant User
    participant BottomSheet
    participant FramerMotion

    User->>BottomSheet: 열기 (isOpen=true)
    BottomSheet->>FramerMotion: animate(y → MID)
    User->>BottomSheet: 드래그 (y축)
    BottomSheet->>BottomSheet: onDragEnd: velocity 검사

    alt 빠른 아래로 (velocity.y > threshold)
        BottomSheet->>BottomSheet: onClose()
    else 빠른 위로 (velocity.y < -threshold)
        BottomSheet->>FramerMotion: animate(y → TOP)
    else 느린 드래그
        BottomSheet->>BottomSheet: 가장 가까운 스냅 계산
        BottomSheet->>FramerMotion: animate(y → nearest_snap)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45분

  • 주의할 파일/영역:
    • src/shared/components/bottomsheet/BottomSheet.tsx (드래그/스냅 로직, 반응형 재계산, velocity 임계값)
    • src/pages/ExamplePage.tsxsrc/pages/ExamplePage2.tsx (중복된 바텀시트 예제 일관성)
    • src/pages/corkagemap/CorkageMap.tsx (isActive/isSheetOpen 상태 흐름 및 z-index/포지셔닝)
    • src/pages/corkagemap/list/* (EditGroup 입력 유효성, List의 상태 전파와 ConfirmationModal 타이밍)

Poem

🐰
바닥에서 살포시 솟구친 시트,
손끝 따라 스냅, 바람결에 닫히네.
그룹을 골라 새로이 빛내며,
모달 속 축하가 살랑 웃고,
코드 밭에 당근 향기 퍼지네. ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 콜키지맵 바텀시트 기능과 저장리스트 구현이라는 주요 변경사항을 명확하게 반영하고 있으며, 실제 파일 변경 내용과 잘 일치합니다.
Description check ✅ Passed PR 설명은 저장소의 템플릿 구조를 따르고 있으며, 작업 내용, PR Point, 이미지, 다음 할 일 등이 모두 포함되어 있습니다.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch corkagemap2.0

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

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: 8

🧹 Nitpick comments (7)
src/pages/corkagemap/CorkageMap.tsx (1)

52-52: 매직 넘버에 대한 설명이 필요합니다.

topSnapVh={17.8} 값의 의미가 명확하지 않습니다. 이 값이 왜 17.8인지, 무엇을 나타내는지 주석으로 설명하거나 상수로 추출하는 것을 권장합니다.

+// 바텀시트 최상단 위치: 화면 높이의 17.8% 지점에서 시작
+const BOTTOM_SHEET_TOP_SNAP_VH = 17.8;
+
 const CorkageMap = () => {
   ...
-  <BottomSheet isOpen={isSheetOpen} onClose={handleSheetClose} topSnapVh={17.8}>
+  <BottomSheet isOpen={isSheetOpen} onClose={handleSheetClose} topSnapVh={BOTTOM_SHEET_TOP_SNAP_VH}>

</comment_end>

src/pages/corkagemap/list/EditGroup.tsx (1)

49-55: alert() 대신 더 나은 UX 패턴을 사용하세요.

alert()는 사용자 경험을 방해하고 모던한 웹 애플리케이션에서는 권장되지 않습니다. 또한 isValid 체크로 버튼이 비활성화되어 있기 때문에 이 alert는 실행되지 않을 것입니다.

다음과 같이 수정하는 것을 권장합니다:

 const handleSave = () => {
-  if (!groupName || !selectedIcon) {
-    alert('그룹명과 마커를 선택해주세요.');
-    return;
-  }
+  // isValid 체크로 이미 방지됨
   onSave({ name: groupName, iconName: selectedIcon, privacy });
 };

또는 인라인 에러 메시지나 토스트 알림을 사용하는 것을 고려하세요.
</comment_end>

src/pages/corkagemap/list/List.tsx (1)

34-39: ID 생성 방식이 충돌 위험이 있습니다.

Date.now()를 사용한 ID 생성은 사용자가 빠르게 여러 그룹을 생성할 경우 충돌이 발생할 수 있습니다. 프로토타입 단계에서는 괜찮지만, 나중에 백엔드 API와 연동할 때는 서버에서 생성된 고유 ID를 사용해야 합니다.

임시 해결책으로 더 안전한 ID 생성을 원한다면:

 const handleSaveGroup = (data: Omit<Group, 'id' | 'count'>) => {
   const newGroup: Group = {
     ...data,
-    id: Date.now(),
+    id: Date.now() + Math.random(), // 충돌 가능성 감소
     count: 0,
   };

또는 임시 ID에 접두사를 사용:

-    id: Date.now(),
+    id: `temp-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,

</comment_end>

src/pages/ExamplePage.tsx (1)

37-173: 로컬 BottomSheet 대신 공유 컴포넌트 재사용 고려

이 파일 안에 BottomSheet 구현이 그대로 들어가 있는데, src/shared/components/bottomsheet/BottomSheet.tsx에도 거의 동일한 구현이 존재합니다. 장기적으로 유지보수를 줄이려면 ExamplePage에서는 공유 BottomSheet를 import 해서 사용하는 형태로 맞추는 게 좋아 보입니다.

src/pages/ExamplePage2.tsx (1)

60-72: topSnapVh 변경 가능성을 고려한 deps 정리 (선택사항)

calculateSnapPx 안에서 topSnapVh를 사용하지만 useEffect의 deps 배열이 빈 배열이라, 부모에서 topSnapVh를 바꾸더라도 스냅 포인트 px 값은 갱신되지 않습니다. 현재는 상수(17.8)를 넘기고 있어서 문제는 없지만, 추후 동적으로 바꿀 계획이 있다면 다음처럼 deps에 포함시키는 편이 안전합니다.

-  useEffect(() => {
+  useEffect(() => {
     const calculateSnapPx = () => {
       setSnapPx({
         TOP: vhToPx(topSnapVh),
         MID: vhToPx(SNAP_POINTS.MID),
         MIN: vhToPx(SNAP_POINTS.MIN),
         HIDDEN: vhToPx(SNAP_POINTS.HIDDEN),
       });
     };
     window.addEventListener('resize', calculateSnapPx);
     return () => window.removeEventListener('resize', calculateSnapPx);
-  }, []);
+  }, [topSnapVh]);
src/shared/components/bottomsheet/BottomSheet.tsx (2)

60-72: topSnapVh에 대한 반응형 스냅 재계산 (선택사항)

여기도 ExamplePage2와 마찬가지로 calculateSnapPx에서 topSnapVh를 사용하지만 deps 배열이 비어 있습니다. 현재는 대부분 고정 값으로 쓸 것 같아 당장 문제는 없지만, prop이 동적으로 바뀔 수 있는 구조라면 아래처럼 deps에 포함하는 편이 React hook 관점에서는 더 자연스럽습니다.

-  useEffect(() => {
+  useEffect(() => {
     const calculateSnapPx = () => {
       setSnapPx({
         TOP: vhToPx(topSnapVh),
         MID: vhToPx(SNAP_POINTS.MID),
         MIN: vhToPx(SNAP_POINTS.MIN),
         HIDDEN: vhToPx(SNAP_POINTS.HIDDEN),
       });
     };
     window.addEventListener('resize', calculateSnapPx);
     return () => window.removeEventListener('resize', calculateSnapPx);
-  }, []);
+  }, [topSnapVh]);

41-187: BottomSheet 단일 소스로의 통합 제안

현재 ExamplePage2 내부 BottomSheet와 이 공용 BottomSheet가 거의 동일한 로직을 두 번 가지고 있습니다. 바텀시트 동작(스냅 지점, 드래그, 오버레이 등)이 앞으로 자주 바뀔 예정이라면, 이 파일만 단일 소스로 유지·개선하고 예제 페이지들은 모두 여기서 export한 컴포넌트를 import 하는 식으로 통합하는 걸 추천드립니다.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9bef061 and 5c3d1e2.

⛔ Files ignored due to path filters (17)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
  • src/pages/corkagemap/list/X.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/editDots.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/plus.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker1.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker10.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker11.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker12.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker2.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker3.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker4.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker5.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker6.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker7.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker8.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/savemarker/SaveMarker9.svg is excluded by !**/*.svg
  • src/pages/corkagemap/save.svg is excluded by !**/*.svg
📒 Files selected for processing (11)
  • package.json (1 hunks)
  • src/pages/ExamplePage.tsx (1 hunks)
  • src/pages/ExamplePage2.tsx (1 hunks)
  • src/pages/corkagemap/CorkageMap.tsx (1 hunks)
  • src/pages/corkagemap/list/ConfirmationModal.tsx (1 hunks)
  • src/pages/corkagemap/list/EditGroup.tsx (1 hunks)
  • src/pages/corkagemap/list/List.tsx (1 hunks)
  • src/pages/corkagemap/list/MyGroup.tsx (1 hunks)
  • src/pages/corkagemap/list/ToggleSwitch.tsx (1 hunks)
  • src/shared/components/bottomsheet/BottomSheet.tsx (1 hunks)
  • src/shared/router/Router.tsx (2 hunks)
🧰 Additional context used
🪛 GitHub Actions: CI (develop)
src/pages/ExamplePage.tsx

[error] 83-83: TypeScript error TS6133: 'event' is declared but its value is never read.

🪛 GitHub Check: build-test
src/pages/ExamplePage.tsx

[failure] 83-83:
'event' is declared but its value is never read.

src/shared/components/bottomsheet/BottomSheet.tsx

[failure] 97-97:
'event' is declared but its value is never read.

src/pages/ExamplePage2.tsx

[failure] 97-97:
'event' is declared but its value is never read.

🔇 Additional comments (9)
src/shared/router/Router.tsx (1)

43-44: 예제 라우트의 목적을 명확히 해주세요.

ExamplePageExamplePage2 라우트가 추가되었습니다. 이것들이 개발/테스트 목적의 임시 라우트인지, 프로덕션에 포함되어야 하는 기능인지 확인이 필요합니다. 만약 테스트용이라면 머지 전에 제거하는 것을 권장합니다.

</comment_end>

Also applies to: 211-218

src/pages/corkagemap/CorkageMap.tsx (1)

1-17: 상태 관리가 잘 구현되었습니다.

바텀시트 열기/닫기 상태와 버튼 활성화 상태를 함께 관리하는 handleSheetClose 구현이 명확하고 올바릅니다.

</comment_end>

src/pages/corkagemap/list/EditGroup.tsx (2)

145-156: 절대 위치 버튼의 반응형 동작을 확인해주세요.

버튼이 calc(75vh - 48px) 위치에 고정되어 있습니다. 주석으로 의도가 설명되어 있지만, 다양한 화면 크기와 바텀시트 높이에서 올바르게 작동하는지 확인이 필요합니다. 특히 스크롤 가능한 콘텐츠와 함께 사용될 때 버튼이 콘텐츠를 가릴 수 있습니다.

다음 시나리오에서 테스트를 권장합니다:

  • 작은 화면 (모바일)
  • 큰 화면 (태블릿)
  • 바텀시트가 완전히 확장된 상태
  • 바텀시트가 중간 위치에 있는 상태
    </comment_end>

68-83: 입력 검증이 잘 구현되었습니다.

10자 제한과 실시간 문자 수 카운터가 올바르게 구현되어 있습니다. 사용자 경험이 좋습니다.

</comment_end>

src/pages/corkagemap/list/List.tsx (2)

100-108: AnimatePresence 사용이 올바릅니다.

모달의 마운트/언마운트 애니메이션을 위한 AnimatePresence 사용이 적절합니다. framer-motion의 권장 패턴을 잘 따르고 있습니다.

</comment_end>


18-26: 상태 관리 구조가 명확합니다.

뷰 전환(list/edit), 그룹 데이터, 모달 상태를 명확하게 분리하여 관리하고 있습니다. 컴포넌트의 의도를 이해하기 쉽습니다.

</comment_end>

package.json (1)

16-16: framer-motion 버전이 최신 버전이며 보안상 문제가 없습니다.

검증 결과:

  • npm 레지스트리 최신 버전: 12.23.24 ✓
  • 현재 package.json 버전: ^12.23.24 ✓
  • 보안 취약점: 없음 ✓

지정된 버전이 최신이고 보안 권고사항상 문제가 없으므로 추가 조치가 필요하지 않습니다.

src/pages/corkagemap/list/ConfirmationModal.tsx (1)

57-57: z-index 충돌 우려는 실제 문제가 아닙니다.

코드 검토 결과, ConfirmationModal의 z-[110]과 BottomSheet의 z-[101]은 충돌하지 않습니다. z-index 값들이 올바르게 계층화되어 있습니다:

  • ConfirmationModal: 110 (최상위)
  • BottomSheet: 101
  • NextButton: 100
  • Footer: 99

ConfirmationModal이 BottomSheet보다 높은 z-index를 가지므로 확인 모달이 다른 컴포넌트 위에 올바르게 표시되는 것이 맞는 동작입니다. 실제 z-index 충돌은 없습니다.

Likely an incorrect or invalid review comment.

src/pages/corkagemap/list/ToggleSwitch.tsx (1)

17-17: layout prop은 framer-motion v12.23.24에서 올바르게 지원됩니다.

검증 결과, framer-motion 버전 12.23.24는 motion.divlayout prop을 완전히 지원합니다. 공식 Motion 문서와 npm 패키지 정보에서 확인되었으므로 호환성 문제가 없습니다.

Comment on lines 66 to 70
{/* 토글 스위치 */}
<div className="flex h-8 cursor-pointer items-center gap-2 rounded-[20px] py-1">
<span className="text-[16px] font-[400] text-[#80818B]">콜키지 정보 on/off</span>
<ToggleSwitch />
</div>
Copy link

@coderabbitai coderabbitai bot Nov 22, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

토글 스위치가 기능과 연결되지 않았습니다.

"콜키지 정보 on/off" 텍스트가 있지만, ToggleSwitch 컴포넌트에 props가 없어서 실제로 어떤 기능도 제어하지 않습니다. 이는 사용자에게 혼란을 줄 수 있습니다.

다음 중 하나를 선택해야 합니다:

  1. 기능 구현: ToggleSwitch를 제어 가능한 컴포넌트로 만들고 실제 콜키지 정보 표시/숨김 기능을 구현
  2. 임시 제거: 아직 구현되지 않았다면 이 UI 요소를 제거하고 나중에 추가

ToggleSwitch.tsx 파일에도 관련 리뷰 코멘트를 남겼습니다.
</comment_end>

🤖 Prompt for AI Agents
In src/pages/corkagemap/list/List.tsx around lines 66-70, the ToggleSwitch is
rendered without props so it does not control anything; make it a controlled
toggle that actually shows/hides corkage info: add a local state (e.g., const
[showCorkage, setShowCorkage] = useState<boolean>(true)), pass value and
onChange props to ToggleSwitch (value={showCorkage} onChange={setShowCorkage}),
and use showCorkage to conditionally render the corkage-related UI elsewhere in
this file; if you prefer to defer implementation instead, remove the entire
toggle block here and reintroduce it once the feature is implemented.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

이건 나중에 할게

Copy link

Choose a reason for hiding this comment

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

@KingSeokJin, 알겠습니다! 나중에 구현하시는 것도 좋은 방법입니다.

추후 작업을 추적하기 위해 follow-up 이슈를 생성하시겠습니까? 원하시면 제가 도와드릴 수 있습니다.

Comment on lines +4 to +13
const ToggleSwitch = () => {
const [isOn, setIsOn] = useState(false);

return (
<button
className={`relative flex h-[31px] w-[54px] items-center rounded-[16px] p-1 transition-colors ${
isOn ? 'bg-[#90212A]' : 'bg-gray-300'
}`}
onClick={() => setIsOn(!isOn)}
aria-pressed={isOn}
Copy link

@coderabbitai coderabbitai bot Nov 22, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

토글 스위치를 제어 가능한 컴포넌트로 변경해야 합니다.

현재 ToggleSwitch는 내부 상태만 가지고 있어서 부모 컴포넌트가 상태를 제어하거나 변경사항을 감지할 수 없습니다. List.tsx에서 "콜키지 정보 on/off" 기능을 구현하려면 이 컴포넌트가 제어 가능해야 합니다.

다음과 같이 수정하는 것을 권장합니다:

-const ToggleSwitch = () => {
-  const [isOn, setIsOn] = useState(false);
+type ToggleSwitchProps = {
+  isOn: boolean;
+  onToggle: (isOn: boolean) => void;
+};
+
+const ToggleSwitch = ({ isOn, onToggle }: ToggleSwitchProps) => {
 
   return (
     <button
       className={`relative flex h-[31px] w-[54px] items-center rounded-[16px] p-1 transition-colors ${
         isOn ? 'bg-[#90212A]' : 'bg-gray-300'
       }`}
-      onClick={() => setIsOn(!isOn)}
+      onClick={() => onToggle(!isOn)}
       aria-pressed={isOn}
     >

</comment_end>

🤖 Prompt for AI Agents
In src/pages/corkagemap/list/ToggleSwitch.tsx around lines 4 to 13, the
component currently holds internal state so parents cannot control or observe
its value; change it to a controlled component by removing internal useState and
accepting props (e.g., checked: boolean, onChange: (newValue: boolean) => void),
use the checked prop instead of isOn for rendering and aria-pressed, and call
onChange(!checked) from the click handler; update any parent (List.tsx) to keep
the boolean state and pass it down plus a handler to update it.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

토글 기능 구현할때 참고하여 반영하겠습니다.

Copy link

Choose a reason for hiding this comment

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

@KingSeokJin 감사합니다! 토글 기능 구현 시 해당 피드백이 도움이 되길 바랍니다. 추가로 필요한 사항이 있으시면 언제든지 말씀해 주세요! 👍

Comment on lines 83 to 119
const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
const { velocity } = info;

// 아래로 빠르게 쓸어내리면 닫기
if (velocity.y > DRAG_VELOCITY_THRESHOLD) {
onClose();
return;
}

// 위로 빠르게 쓸어올리면 최대 높이로
if (velocity.y < -DRAG_VELOCITY_THRESHOLD) {
controls.start('snapTop');
return;
}

// 2. 느린 드래그 (위치 기반 스냅)
// 현재 y 위치 가져오기
const currentY = sheetRef.current ? sheetRef.current.getBoundingClientRect().y : 0;

// 현재 vh 값 계산 (대략적)
const currentVh = (currentY / window.innerHeight) * 100;

// 각 스냅 지점의 중간값 계산
const midPointTopMid = (SNAP_POINTS.TOP + SNAP_POINTS.MID) / 2;
const midPointMidMin = (SNAP_POINTS.MID + SNAP_POINTS.MIN) / 2;
const midPointMinClose = (SNAP_POINTS.MIN + SNAP_POINTS.HIDDEN) / 2;

if (currentVh < midPointTopMid) {
controls.start('snapTop'); // 최대 높이로
} else if (currentVh < midPointMidMin) {
controls.start('snapMid'); // 중간 높이로
} else if (currentVh < midPointMinClose) {
controls.start('snapMin'); // 최소 높이로
} else {
onClose(); // 닫기
}
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

onDragEndevent 미사용으로 TS6133 오류 발생

CI 로그대로 onDragEnd에서 event를 선언만 하고 읽지 않아 TS6133(noUnusedParameters)로 빌드가 깨집니다. event를 사용하지 않을 거라면, 다음과 같이 “사용한 것”으로 처리해 컴파일 경고를 제거하는 쪽이 안전합니다.

-  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
-    const { velocity } = info;
+  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
+    void event; // 사용하지 않는 파라미터임을 명시적으로 표시
+    const { velocity } = info;

수정 후 yarn build/npm run build로 CI 에러가 사라지는지 한 번 확인 부탁드립니다.


🏁 Script executed:

#!/bin/bash
# 1. ExamplePage.tsx 파일 찾기
fd -t f "ExamplePage.tsx"

Length of output: 25


🏁 Script executed:

#!/bin/bash
# 2. tsconfig.json 확인 (noUnusedParameters 설정)
fd -t f "tsconfig.json" | head -5

Length of output: 13


🏁 Script executed:

#!/bin/bash
# 3. ExamplePage.tsx에서 onDragEnd 함수 주변 코드 확인 (더 넓은 범위)
if fd -t f "ExamplePage.tsx" > /dev/null 2>&1; then
  FILE=$(fd -t f "ExamplePage.tsx" | head -1)
  if [ -n "$FILE" ]; then
    echo "=== File: $FILE ==="
    sed -n '80,125p' "$FILE"
  fi
fi

Length of output: 1311


🏁 Script executed:

#!/bin/bash
# 4. event 파라미터가 onDragEnd 함수 내에서 사용되는지 검색
if fd -t f "ExamplePage.tsx" > /dev/null 2>&1; then
  FILE=$(fd -t f "ExamplePage.tsx" | head -1)
  if [ -n "$FILE" ]; then
    echo "=== Checking for 'event' usage in ExamplePage.tsx ==="
    rg -n "event" "$FILE" -A 5 -B 5
  fi
fi

Length of output: 382


🏁 Script executed:

#!/bin/bash
# tsconfig.json에서 noUnusedParameters 설정 확인
cat tsconfig.json

Length of output: 118


🏁 Script executed:

#!/bin/bash
# tsconfig.app.json 확인
cat tsconfig.app.json

Length of output: 791


onDragEndevent 파라미터 미사용으로 TS6133 오류 발생

검증 결과 src/pages/ExamplePage.tsx 83번 라인의 onDragEnd 함수에서 event 파라미터가 선언되지만 함수 본문에서 사용되지 않고 있습니다. tsconfig.app.json에서 "noUnusedParameters": true로 설정되어 있으므로, 현재 코드는 TypeScript 컴파일 오류(TS6133)를 발생시킵니다.

제안된 수정은 정확하고 표준적인 패턴입니다:

-  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
-    const { velocity } = info;
+  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
+    void event; // 사용하지 않는 파라미터임을 명시적으로 표시
+    const { velocity } = info;
🧰 Tools
🪛 GitHub Actions: CI (develop)

[error] 83-83: TypeScript error TS6133: 'event' is declared but its value is never read.

🪛 GitHub Check: build-test

[failure] 83-83:
'event' is declared but its value is never read.

🤖 Prompt for AI Agents
src/pages/ExamplePage.tsx around lines 83-119: the onDragEnd function declares
an unused event parameter which triggers TS6133; fix by removing the unused
event parameter from the function signature (or rename it to _event to
intentionally mark it unused) and adjust the type annotation so the function
only requires the PanInfo parameter (ensure any callers/handlers remain
compatible after the signature change).

Comment on lines 97 to 131
const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
const { velocity } = info;

// 1. 빠른 플릭(flick) 제스처 감지
if (velocity.y > DRAG_VELOCITY_THRESHOLD) {
onClose(); // (useEffect[isOpen]이 y를 HIDDEN으로 애니메이션함)
return;
}
if (velocity.y < -DRAG_VELOCITY_THRESHOLD) {
animate(y, snapPx.TOP, { type: 'tween', duration: 0.3, ease: 'easeOut' });
setCurrentSnap('TOP');
return;
}

// 2. 느린 드래그 (위치 기반 스냅)
const currentY = y.get(); // 현재 y 픽셀 값

// 각 스냅 지점의 중간값 계산
const midPointTopMid = (snapPx.TOP + snapPx.MID) / 2;
const midPointMidMin = (snapPx.MID + snapPx.MIN) / 2;
const midPointMinClose = (snapPx.MIN + snapPx.HIDDEN) / 2;

if (currentY < midPointTopMid) {
animate(y, snapPx.TOP, { type: 'tween', duration: 0.3, ease: 'easeOut' });
setCurrentSnap('TOP');
} else if (currentY < midPointMidMin) {
animate(y, snapPx.MID, { type: 'tween', duration: 0.3, ease: 'easeOut' });
setCurrentSnap('MID');
} else if (currentY < midPointMinClose) {
animate(y, snapPx.MIN, { type: 'tween', duration: 0.3, ease: 'easeOut' });
setCurrentSnap('MIN');
} else {
onClose(); // (useEffect[isOpen]이 y를 HIDDEN으로 애니메이션함)
}
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

공용 BottomSheet의 onDragEnd도 TS6133 대상

실제 앱에서 사용하는 공용 BottomSheet에서도 onDragEndevent 파라미터를 사용하지 않아 TS6133이 발생합니다. 빌드를 깨는 부분이므로 여기서도 동일하게 처리해 주는 게 좋겠습니다.

-  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
-    const { velocity } = info;
+  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
+    void event;
+    const { velocity } = info;

🏁 Script executed:

#!/bin/bash
# BottomSheet 파일 존재 및 onDragEnd 함수 확인
find . -name "BottomSheet.tsx" -type f 2>/dev/null | head -5

Length of output: 51


🏁 Script executed:

#!/bin/bash
# onDragEnd 함수의 event 파라미터 사용 여부 확인
if [ -f "src/shared/components/bottomsheet/BottomSheet.tsx" ]; then
  sed -n '97,131p' "src/shared/components/bottomsheet/BottomSheet.tsx"
fi

Length of output: 1273


🏁 Script executed:

#!/bin/bash
# TypeScript 설정 확인 (tsconfig.json 내 noUnusedParameters 설정)
if [ -f "tsconfig.json" ]; then
  cat tsconfig.json | grep -A5 -B5 "noUnusedParameters\|noImplicitAny\|strict"
fi

Length of output: 0


🏁 Script executed:

#!/bin/bash
# ExamplePage2와의 유사 패턴 확인
rg -n "const onDragEnd" --type=tsx --type=ts -C3

Length of output: 27


🏁 Script executed:

#!/bin/bash
# tsconfig.json 전체 확인
cat tsconfig.json

Length of output: 118


🏁 Script executed:

#!/bin/bash
# ExamplePage2 onDragEnd 검색 (grep 사용)
grep -rn "onDragEnd" --include="*.tsx" --include="*.ts" src/ 2>/dev/null | head -20

Length of output: 580


🏁 Script executed:

#!/bin/bash
# package.json의 빌드 및 타입체크 스크립트 확인
cat package.json | grep -A10 "scripts"

Length of output: 248


🏁 Script executed:

#!/bin/bash
# tsconfig.app.json 확인 (strict 모드 및 noUnusedParameters)
cat tsconfig.app.json

Length of output: 791


🏁 Script executed:

#!/bin/bash
# ExamplePage2의 onDragEnd를 상세히 확인 (라인 97 주변)
sed -n '95,105p' src/pages/ExamplePage2.tsx

Length of output: 349


BottomSheet의 onDragEnd 파라미터 미사용 확인

검증 결과, 리뷰 코멘트의 지적이 정확합니다.

  • tsconfig.app.json"noUnusedParameters": true로 설정되어 있음
  • BottomSheet.tsx 라인 97의 onDragEnd 함수에서 event 파라미터가 실제로 미사용 중
  • 빌드 스크립트(tsc -b && vite build)에서 TypeScript 컴파일 단계에서 TS6133 오류 발생
  • ExamplePage.tsx(라인 83)와 ExamplePage2.tsx(라인 97)도 동일한 문제 보유

제안된 수정(void event;)이 올바른 TypeScript 관례이며, 빌드 실패를 해결합니다.

-  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
-    const { velocity } = info;
+  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
+    void event;
+    const { velocity } = info;
🧰 Tools
🪛 GitHub Check: build-test

[failure] 97-97:
'event' is declared but its value is never read.

🤖 Prompt for AI Agents
In src/shared/components/bottomsheet/BottomSheet.tsx around lines 97 to 131, the
onDragEnd signature includes an unused first parameter (event) which triggers
TS6133 under "noUnusedParameters"; to fix, mark the parameter as intentionally
unused by referencing it with a void expression (e.g., void event;) at the start
of the function or rename it to _event and reference it similarly, then run the
build to confirm the TypeScript error is resolved; apply the same void-event fix
to ExamplePage.tsx (line 83) and ExamplePage2.tsx (line 97) where the same
unused-parameter error occurs.

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: 0

♻️ Duplicate comments (4)
src/shared/components/bottomsheet/BottomSheet.tsx (1)

97-131: onDragEnd_event 미사용으로 TS6133 계속 발생 가능

이전 리뷰에서 지적됐던 것처럼, tsconfig.app.jsonnoUnusedParameters: true가 켜져 있다면, 이름만 _event로 바꿔도 TypeScript 컴파일러는 여전히 “사용되지 않은 파라미터”로 간주합니다.

TS6133를 확실히 피하려면 파라미터를 실제로 한 번 읽어 주거나 시그니처에서 제거해야 합니다. 아래처럼 void로 소비하는 패턴이 무난합니다.

-  const onDragEnd = (_event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
-    const { velocity } = info;
+  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
+    void event;
+    const { velocity } = info;

같은 패턴을 사용하는 다른 파일(예: ExamplePage.tsx, ExamplePage2.tsx)에도 동일하게 적용해 두면 CI에서 타입 체크 실패를 막을 수 있습니다.

src/pages/ExamplePage2.tsx (1)

97-131: 여기도 _event 미사용으로 TS6133 위험 (ExamplePage와 동일 패턴)

이 파일의 onDragEnd도 첫 번째 인자 _event를 전혀 읽지 않아, noUnusedParameters: true 설정에서는 컴파일 에러가 날 수 있습니다. 이름만 _event로 바꾸면 ESLint 규칙에는 도움이 될 수 있지만, TypeScript 컴파일러는 여전히 “미사용”으로 판단합니다.

공용 컴포넌트와 동일하게 void로 소모해 주는 식으로 정리하는 걸 추천드립니다.

-  const onDragEnd = (_event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
-    const { velocity } = info;
+  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
+    void event;
+    const { velocity } = info;
src/pages/ExamplePage.tsx (2)

83-119: onDragEnd_event 미사용 – TS6133 여전히 남아 있을 가능성

이전 리뷰에서 지적된 것처럼, _event로 이름만 바꾸면 TypeScript의 noUnusedParameters 에러는 그대로 남습니다. 이 구현에서도 _event를 전혀 읽지 않고 있어 타입 체크 단계에서 막힐 수 있습니다.

공용 BottomSheet에서와 동일하게, 파라미터를 실제로 한 번 소비하도록 변경하는 쪽을 권장합니다.

-  const onDragEnd = (_event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
-    const { velocity } = info;
+  const onDragEnd = (event: MouseEvent | TouchEvent | PointerEvent, info: PanInfo) => {
+    void event;
+    const { velocity } = info;

151-162: height: calc(100vh - ${SNAP_POINTS.TOP})에서 단위 누락으로 CSS 무효 가능성

SNAP_POINTS.TOP이 vh 단위 전제로 정의되어 있는데, height 계산에서 ${SNAP_POINTS.TOP} 뒤에 단위가 없어 calc(100vh - 17.8) 같은 형태가 됩니다. 이 값은 CSS에서 유효한 길이 단위가 아니어서, 브라우저에 따라 height가 무시될 수 있습니다.

아래처럼 vh 단위를 명시하는 편이 안전합니다.

-        style={{
-          height: `calc(100vh - ${SNAP_POINTS.TOP})`, // 최대 높이
+        style={{
+          height: `calc(100vh - ${SNAP_POINTS.TOP}vh)`, // 최대 높이
🧹 Nitpick comments (5)
src/shared/components/bottomsheet/BottomSheet.tsx (2)

52-72: useEffect에서 topSnapVh 의존성 누락

calculateSnapPx 안에서 topSnapVh를 사용하지만 의존성 배열이 []라서, 부모가 topSnapVh를 변경해도 스냅 지점(px)이 갱신되지 않습니다.

topSnapVh를 의존성에 추가해서 prop 변동 시에도 올바르게 재계산되도록 하는 편이 안전해 보입니다.

-  useEffect(() => {
+  useEffect(() => {
     const calculateSnapPx = () => {
       setSnapPx({
         TOP: vhToPx(topSnapVh),
         MID: vhToPx(SNAP_POINTS.MID),
         MIN: vhToPx(SNAP_POINTS.MIN),
         HIDDEN: vhToPx(SNAP_POINTS.HIDDEN),
       });
     };
     window.addEventListener('resize', calculateSnapPx);
     return () => window.removeEventListener('resize', calculateSnapPx);
-  }, []);
+  }, [topSnapVh]);

111-167: 느린 드래그로 “아래로 닫기”가 사실상 불가능한 스냅/제약 조합

midPointMinClose를 기준으로 느린 드래그 시 바텀시트를 닫는 로직을 두셨지만, dragConstraints.bottomsnapPx.MIN(열려 있는 최소 위치)라서 사용자가 천천히 아래로 끌어도 currentYmidPointMinClose까지 내려가지 못해 onClose() 분기로 거의 진입하지 못합니다.

의도하신 UX가 “천천히 내려도 닫힘”이라면:

  • dragConstraints.bottomsnapPx.HIDDEN 근처로 넓히거나,
  • 또는 midPointMinClosesnapPx.MIN 기준으로 다시 정의

하는 쪽이 자연스러울 것 같습니다. 지금 상태도 기능상 치명적이진 않지만, 기대한 제스처와 실제 동작이 다를 수 있어 한 번 더 UX 관점에서 점검해 보시면 좋겠습니다.

src/pages/ExamplePage2.tsx (2)

52-72: useEffecttopSnapVh 의존성 추가 권장 (lint 경고 반영)

calculateSnapPx 안에서 topSnapVh를 사용하지만 의존성 배열이 비어 있어, ESLint 경고대로 prop 변경 시 스냅 지점이 갱신되지 않습니다.

topSnapVh를 의존성에 포함해 두면 부모가 최대 높이를 바꿀 때도 안전하게 따라갑니다.

-  useEffect(() => {
+  useEffect(() => {
     const calculateSnapPx = () => {
       setSnapPx({
         TOP: vhToPx(topSnapVh),
         MID: vhToPx(SNAP_POINTS.MID),
         MIN: vhToPx(SNAP_POINTS.MIN),
         HIDDEN: vhToPx(SNAP_POINTS.HIDDEN),
       });
     };
     window.addEventListener('resize', calculateSnapPx);
     return () => window.removeEventListener('resize', calculateSnapPx);
-  }, []);
+  }, [topSnapVh]);

8-131: 공용 BottomSheet와 로직이 1:1로 중복 – import로 통합 권장

src/shared/components/bottomsheet/BottomSheet.tsx의 구현과 이 파일 상단 BottomSheet 구현이 거의 동일해서, 두 군데가 앞으로 쉽게 벌어질 수 있습니다.

예시 페이지라 하더라도, 가능하면 공용 컴포넌트를 import 해서 사용하는 쪽이 유지보수성이 좋아 보입니다.

예시:

-import { motion, useMotionValue, useTransform, animate } from 'framer-motion';
-import { useState, useEffect } from 'react';
-import type { ReactNode } from 'react';
-import type { PanInfo } from 'framer-motion';
+import type { ReactNode } from 'react';
+import BottomSheet from '@/shared/components/bottomsheet/BottomSheet';
...
-// BottomSheet.tsx 컴포넌트 코드
-...
-const BottomSheet = ({ isOpen, onClose, children }: BottomSheetProps) => {
-  ...
-};
+// 공용 BottomSheet 컴포넌트를 사용합니다.

(실제 import 경로는 프로젝트 alias에 맞춰 조정 필요)

src/pages/ExamplePage.tsx (1)

11-174: ExamplePage 내 BottomSheet 구현도 공용 컴포넌트로 대체 고려

이 파일도 ExamplePage2, src/shared/components/bottomsheet/BottomSheet.tsx와 별도의 BottomSheet 구현을 갖고 있어, 총 3군데에서 바텀시트 로직이 관리되는 구조입니다. 향후 스냅 포인트나 제스처 로직을 수정할 때 동기화 비용이 커질 수 있습니다.

예제 페이지라 하더라도:

  • 공용 BottomSheet만 남기고,
  • ExamplePage/ExamplePage2는 모두 import 해서 사용하는 형태

로 통합하면 유지보수/버그 방지 측면에서 더 깔끔할 것 같습니다.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5c3d1e2 and ce22fe7.

📒 Files selected for processing (3)
  • src/pages/ExamplePage.tsx (1 hunks)
  • src/pages/ExamplePage2.tsx (1 hunks)
  • src/shared/components/bottomsheet/BottomSheet.tsx (1 hunks)
🧰 Additional context used
🪛 GitHub Check: build-test
src/pages/ExamplePage2.tsx

[warning] 72-72:
React Hook useEffect has a missing dependency: 'topSnapVh'. Either include it or remove the dependency array. If 'setSnapPx' needs the current value of 'topSnapVh', you can also switch to useReducer instead of useState and read 'topSnapVh' in the reducer

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: 0

♻️ Duplicate comments (1)
src/pages/corkagemap/list/List.tsx (1)

119-122: 토글 스위치가 여전히 기능과 연결되지 않았습니다.

"콜키지 정보 on/off" 텍스트와 함께 ToggleSwitch 컴포넌트가 렌더링되지만, props가 없어 아무 기능도 제어하지 않습니다. 이는 이전 리뷰에서도 지적된 사항입니다.

제어 가능한 토글로 만들거나, 아직 구현되지 않았다면 해당 UI 요소를 제거하는 것을 권장합니다.

🧹 Nitpick comments (5)
src/pages/corkagemap/list/MyGroup.tsx (2)

72-74: 키보드 접근성 개선이 필요합니다.

점 메뉴 버튼이 마우스 클릭만 지원하고 키보드 탐색을 지원하지 않습니다.

다음과 같이 수정하여 접근성을 개선하세요:

-        <div className="cursor-pointer p-1" onClick={handleToggleMenu}>
+        <button
+          className="cursor-pointer p-1"
+          onClick={handleToggleMenu}
+          onKeyDown={(e) => {
+            if (e.key === 'Enter' || e.key === ' ') {
+              e.preventDefault();
+              handleToggleMenu();
+            }
+          }}
+          aria-label="그룹 메뉴 열기"
+          aria-expanded={isMenuOpen}
+        >
           <img src={EditDots} alt="EditDots" />
-        </div>
+        </button>

45-46: 아이콘 폴백 처리를 고려하세요.

iconNamesmallMarkers 맵에 없는 경우 아이콘이 표시되지 않습니다. 현재 조건부 렌더링으로 안전하게 처리되지만, 기본 아이콘이나 플레이스홀더를 표시하면 사용자 경험이 향상될 수 있습니다.

Also applies to: 66-66

src/pages/corkagemap/list/List.tsx (2)

83-83: ID 생성 방식을 개선하는 것을 고려하세요.

Date.now()를 ID로 사용하는 것은 대부분의 경우 작동하지만, 빠르게 연속으로 그룹을 생성하면 ID 충돌이 발생할 수 있습니다.

더 안전한 대안:

  • 카운터 기반 ID (예: useRef로 관리)
  • UUID 라이브러리 사용
  • 서버에서 ID 생성 (향후 백엔드 통합 시)

71-78: 상태 업데이트 패턴을 더 명확하게 개선할 수 있습니다.

Line 72에서 myGroups.find()로 이전 상태에서 그룹을 찾고 있는데, Line 63-69의 setMyGroups가 아직 반영되지 않았을 수 있습니다. 현재는 data와 병합하여 동작하지만, 더 명확한 패턴은 모든 필요한 정보를 data에서 직접 구성하는 것입니다.

다음과 같이 리팩토링을 고려하세요:

      const updatedGroup = myGroups.find((g) => g.id === editingGroupId);
-      const newGroupInfo = { ...updatedGroup, ...data } as Group;
+      const newGroupInfo: Group = {
+        id: editingGroupId,
+        count: updatedGroup?.count ?? 0,
+        ...data,
+      };
src/pages/corkagemap/list/EditGroup.tsx (1)

64-70: 유효성 검증 피드백을 개선하는 것을 고려하세요.

alert()를 사용한 유효성 검증은 기능적으로 작동하지만, 인라인 에러 메시지나 토스트 알림이 더 나은 사용자 경험을 제공합니다. Line 60의 isValid 체크로 Line 162의 버튼을 비활성화하므로, 이 alert는 실제로는 방어 코드입니다.

alert()를 제거하거나, 인라인 에러 메시지 UI로 교체하는 것을 고려하세요.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ce22fe7 and bb7fc5b.

⛔ Files ignored due to path filters (2)
  • src/pages/corkagemap/list/edit.svg is excluded by !**/*.svg
  • src/pages/corkagemap/list/trash.svg is excluded by !**/*.svg
📒 Files selected for processing (4)
  • src/pages/corkagemap/list/ConfirmationModal.tsx (1 hunks)
  • src/pages/corkagemap/list/EditGroup.tsx (1 hunks)
  • src/pages/corkagemap/list/List.tsx (1 hunks)
  • src/pages/corkagemap/list/MyGroup.tsx (1 hunks)
🧰 Additional context used
🪛 GitHub Check: build-test
src/pages/corkagemap/list/EditGroup.tsx

[warning] 42-42:
'data' is defined but never used. Allowed unused args must match /^_$/u

src/pages/corkagemap/list/MyGroup.tsx

[warning] 41-41:
'id' is defined but never used. Allowed unused args must match /^_$/u


[warning] 40-40:
'id' is defined but never used. Allowed unused args must match /^_$/u

🔇 Additional comments (5)
src/pages/corkagemap/list/MyGroup.tsx (1)

84-105: 이전 리뷰 코멘트가 해결되었습니다.

편집 및 삭제 버튼이 이제 적절한 onClick 핸들러를 가지고 있으며, 각각 onEdit(id)onDelete(id)를 호출합니다. 메뉴가 닫히고 부모 컴포넌트에 올바르게 알림을 전달합니다.

src/pages/corkagemap/list/ConfirmationModal.tsx (2)

46-74: 이전 리뷰 코멘트가 해결되었습니다.

모달이 이제 mode prop을 받아 생성/편집/삭제 상황에 맞는 메시지를 표시합니다. Switch 문을 사용한 구현이 명확하고 확장 가능합니다.


59-60: 아이콘 및 색상 처리가 안전합니다.

iconName이 맵에 없는 경우를 조건부 렌더링과 fallback 값으로 적절히 처리하고 있습니다.

Also applies to: 88-88

src/pages/corkagemap/list/EditGroup.tsx (2)

87-97: 입력 길이 제한 구현이 우수합니다.

onChange에서 최대 길이를 강제하고 실시간 카운터를 제공하는 것은 좋은 UX 패턴입니다.


159-169: 버튼 위치 계산을 확인하세요.

Line 159의 주석에는 "680px / 852px = 79.8% -> ~80vh"라고 되어 있지만, Line 168에서는 75vh를 사용하고 있습니다. 이것이 의도적인 조정인지 확인이 필요합니다.

다양한 화면 크기에서 버튼 위치가 적절한지 테스트해보세요.

@TakioN
Copy link
Member

TakioN commented Nov 23, 2025

음 savemarker가 svg내부에 겹치는게 많아서 하나의 파일로 만들고 색을 props로 받으면 유지보수에 좋지 않을까? 라는 고민을 했었는데 몇몇 marker는 안에가 좀 복잡하게 생겨서 힘들거 같네요... 아모튼 고생했어유!

@KingSeokJin
Copy link
Collaborator Author

음 savemarker가 svg내부에 겹치는게 많아서 하나의 파일로 만들고 색을 props로 받으면 유지보수에 좋지 않을까? 라는 고민을 했었는데 몇몇 marker는 안에가 좀 복잡하게 생겨서 힘들거 같네요... 아모튼 고생했어유!

음 비슷하게 했던거같은데 초반에 제가 marker svg 따로 한 파일에 몰아넣고 import를 하나만해서 말씀하신대로 꺼내쓰려고했는데...! 왠지모르게 잘 안되서... 해당 부분은 추후 유지보수 단계에서 최우선 수정사안으로 고려해보겠습니다...!

@KingSeokJin KingSeokJin merged commit 9f2def9 into develop Nov 23, 2025
3 checks passed
@KingSeokJin KingSeokJin deleted the corkagemap2.0 branch November 23, 2025 09:50
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.

3 participants