Skip to content

[feat] 사용자 채팅방 이름 변경 및 채팅방 나가기 기능 추가#258

Open
ParkSungju01 wants to merge 5 commits intodevelopfrom
255-feat-채팅방-삭제-및-이름-변경-기능-추가

Hidden character warning

The head ref may contain hidden characters: "255-feat-\ucc44\ud305\ubc29-\uc0ad\uc81c-\ubc0f-\uc774\ub984-\ubcc0\uacbd-\uae30\ub2a5-\ucd94\uac00"
Open

[feat] 사용자 채팅방 이름 변경 및 채팅방 나가기 기능 추가#258
ParkSungju01 wants to merge 5 commits intodevelopfrom
255-feat-채팅방-삭제-및-이름-변경-기능-추가

Conversation

@ParkSungju01
Copy link
Copy Markdown
Contributor

@ParkSungju01 ParkSungju01 commented Apr 4, 2026

✨ 요약

  • 사용자가 자신에게 보이는 채팅방의 이름을 수정하거나 채팅방을 나갈 수 있는 기능을 구현했습니다.

😎 해결한 이슈

close #255

✅ 작업 내용

  • patchChatRoom, DeleteChatRoom API 추가
  • 채팅창 목록에서 채팅방을 길게 누를시 contextMessage 표시
  • 사용자 화면에서의 채팅방 이름을 원하는 값으로 설정 가능
  • 채팅방 이름 수정시 공백을 입력하면 기본값으로 저장
  • 채팅방 나가기를 선택시 해당 채팅방 삭제

🧪 테스트

  • pnpm lint

Summary by CodeRabbit

  • 새로운 기능
    • 채팅 목록에서 롱프레스(길게 누르기)로 각 채팅방 컨텍스트 메뉴를 열 수 있습니다.
    • 컨텍스트 메뉴에서 채팅방 이름 변경 및 채팅방 나가기(삭제)를 수행할 수 있는 UI(모달 포함)가 추가되었습니다.
    • 롱프레스와 외부 탭 감지를 위한 제스처 처리로 사용자 상호작용이 개선되었습니다.

@ParkSungju01 ParkSungju01 linked an issue Apr 4, 2026 that may be closed by this pull request
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

Walkthrough

채팅방 이름 변경 및 삭제 기능이 추가되었습니다. API에 patchChatRoomName(chatRoomId, name)deleteChatRoom(chatRoomId)가 추가되고, 이에 대응하는 React Query mutation 키 및 뮤테이션(updateRoomName, deleteRoom)과 훅(useUpdateChatRoomNameMutation, useDeleteChatRoomMutation)이 구현되었습니다. UI 쪽에서는 터치 기반 장기누름 훅(useLongPress)과 외부탭 해제 훅(useOutsideTapDismiss)이 추가되고, 컨텍스트 메뉴 컴포넌트(ChatRoomContextMenu)와 Chat 리스트 항목의 long-press 처리, 이름 변경용 바텀 모달 및 채팅방 나가기(삭제) 확인 모달이 연결되었습니다.

Possibly related PRs

Suggested reviewers

  • ff1451
🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PR 제목이 주요 변경사항을 정확히 반영하고 있습니다. 채팅방 이름 변경 및 나가기 기능 추가라는 핵심 내용이 명확합니다.
Linked Issues check ✅ Passed 모든 코딩 요구사항이 충족되었습니다. 길게 누르기 감지(useLongPress), 컨텍스트 메뉴, 이름 변경 API/UI, 삭제 API/UI가 모두 구현되었습니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 #255 이슈의 요구사항과 일치합니다. 길게 누르기, 이름 변경, 채팅방 삭제 관련 코드만 포함되어 있습니다.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 255-feat-채팅방-삭제-및-이름-변경-기능-추가

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

❤️ Share

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

Copy link
Copy Markdown
Contributor

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

🧹 Nitpick comments (2)
src/pages/Chat/index.tsx (1)

13-14: 상대경로 import를 @/* alias로 통일해 주세요.

해당 파일의 신규 import는 프로젝트 alias 규칙과 맞추는 것이 좋습니다.

As per coding guidelines **/*.{ts,tsx}: "Use @/* alias for import paths instead of relative paths".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Chat/index.tsx` around lines 13 - 14, The imports in this file use
relative paths; update them to the project alias style by replacing
'./components/ChatRoomContextMenu' and './hooks/useChat' with the
'@/pages/Chat/components/ChatRoomContextMenu' and '@/pages/Chat/hooks/useChat'
(or the correct alias-targeted paths for these modules) so that
ChatRoomContextMenu and useChat are imported via the `@/`* alias consistent with
the repo rule for .ts/.tsx imports.
src/apis/chat/index.ts (1)

53-66: 신규 API 응답 타입을 명시해주세요.

apiClient.patch/apiClient.delete의 응답 타입이 빠져 있어 호출부 타입 안정성이 약해집니다. src/apis/chat/entity.ts에 도메인 응답 타입을 정의하고 제네릭으로 연결하는 게 좋습니다.

As per coding guidelines src/apis/**: "요청/응답 타입이 명시되어 있는지" and src/apis/**/*.ts: "Define API response types in the domain-specific entity.ts file".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/apis/chat/index.ts` around lines 53 - 66, patchChatRoomName and
deleteChatRoom call apiClient.patch/delete without specifying response generics,
reducing type safety; update these functions to import the appropriate response
types from src/apis/chat/entity.ts (e.g., ChatRoomNamePatchResponse,
ChatRoomDeleteResponse) and pass them as generics to apiClient.patch and
apiClient.delete respectively so the returned Promise is strongly typed (refer
to functions patchChatRoomName and deleteChatRoom and the domain types in
entity.ts).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/Chat/components/ChatRoomContextMenu.tsx`:
- Around line 23-34: The calculated menuWidth/menuHeight (and menuItemHeight)
used for adjustedX/adjustedY do not match the hardcoded class sizes w-[161px]
h-[159px], causing incorrect positioning; either make the numeric constants
equal to the CSS sizes or (better) measure the rendered element using menuRef
(e.g., in a useLayoutEffect) and compute menuWidth/menuHeight from
menuRef.current.getBoundingClientRect() before computing adjustedX/adjustedY so
the positioning uses the actual rendered width/height; update references to
menuWidth, menuHeight, and menuItemHeight (or remove menuItemHeight if measuring
full height) and ensure the position math uses the measured values.

In `@src/pages/Chat/index.tsx`:
- Around line 319-320: The menu entry with label '알림 끄기' is a no-op; either wire
it to the actual mute toggling function or remove/hide it. Locate the menu items
array in Chat/index.tsx where { label: '알림 끄기', onClick: () => {} } is defined
and change onClick to call the existing toggleMute(...) helper (passing the
current chat id or chat object and then closing the menu), or conditionally
filter out this item when toggleMute is not available/ready so the inert action
never appears to users.
- Around line 295-299: When applying the room name change in the onClick handler
for changeRoomName, normalize newRoomName by trimming whitespace and send an
explicit empty string (or the server's default signal) if the trimmed result is
empty; i.e., compute a normalizedName = newRoomName.trim() and pass
normalizedName === '' ? '' : normalizedName to updateRoomName({ chatRoomId:
roomId, name: normalizedName }) while still calling setChangeRoomName(null) as
before, referencing the changeRoomName, setChangeRoomName, updateRoomName and
newRoomName symbols.
- Around line 267-271: The click handler currently calls
deleteChatRoom(leaveRoom.roomId) without awaiting or handling the Promise (using
setLeaveRoom and leaveRoom); update the handler to guard for leaveRoom, then
call the async deleteChatRoom via await inside an async function or use
.then/.catch to handle success and failure, and ensure you reset
setLeaveRoom(null) only on success or always as desired while logging or
displaying errors on rejection (reference functions/variables: setLeaveRoom,
leaveRoom, deleteChatRoom).

---

Nitpick comments:
In `@src/apis/chat/index.ts`:
- Around line 53-66: patchChatRoomName and deleteChatRoom call
apiClient.patch/delete without specifying response generics, reducing type
safety; update these functions to import the appropriate response types from
src/apis/chat/entity.ts (e.g., ChatRoomNamePatchResponse,
ChatRoomDeleteResponse) and pass them as generics to apiClient.patch and
apiClient.delete respectively so the returned Promise is strongly typed (refer
to functions patchChatRoomName and deleteChatRoom and the domain types in
entity.ts).

In `@src/pages/Chat/index.tsx`:
- Around line 13-14: The imports in this file use relative paths; update them to
the project alias style by replacing './components/ChatRoomContextMenu' and
'./hooks/useChat' with the '@/pages/Chat/components/ChatRoomContextMenu' and
'@/pages/Chat/hooks/useChat' (or the correct alias-targeted paths for these
modules) so that ChatRoomContextMenu and useChat are imported via the `@/`* alias
consistent with the repo rule for .ts/.tsx imports.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 05358e60-3c01-40b7-bcba-07f0adef8238

📥 Commits

Reviewing files that changed from the base of the PR and between 822ad69 and 2d00b80.

📒 Files selected for processing (8)
  • src/apis/chat/index.ts
  • src/apis/chat/mutations.ts
  • src/pages/Chat/components/ChatRoomContextMenu.tsx
  • src/pages/Chat/hooks/useChat.ts
  • src/pages/Chat/hooks/useChatMutations.ts
  • src/pages/Chat/index.tsx
  • src/utils/hooks/useLongPress.ts
  • src/utils/hooks/useOutsideTapDismiss.ts

Comment on lines +319 to +320
{ label: '알림 끄기', onClick: () => {} },
{
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

동작 없는 메뉴 액션은 제거하거나 실제 기능에 연결해 주세요.

'알림 끄기'가 no-op이라 사용자 입장에서 오작동처럼 보입니다. toggleMute에 연결하거나, 준비 전이면 메뉴에서 숨기는 편이 낫습니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Chat/index.tsx` around lines 319 - 320, The menu entry with label
'알림 끄기' is a no-op; either wire it to the actual mute toggling function or
remove/hide it. Locate the menu items array in Chat/index.tsx where { label: '알림
끄기', onClick: () => {} } is defined and change onClick to call the existing
toggleMute(...) helper (passing the current chat id or chat object and then
closing the menu), or conditionally filter out this item when toggleMute is not
available/ready so the inert action never appears to users.

Copy link
Copy Markdown
Contributor

@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

♻️ Duplicate comments (1)
src/pages/Chat/index.tsx (1)

324-324: ⚠️ Potential issue | 🟡 Minor

'알림 끄기' 메뉴가 동작하지 않습니다.

onClick 핸들러가 있어 사용자에게 오작동처럼 보입니다. 실제 기능에 연결하거나 메뉴에서 숨겨 주세요.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Chat/index.tsx` at line 324, The menu entry with label '알림 끄기'
currently has an empty onClick (() => {}) which makes it nonfunctional; replace
the empty handler with the real notification toggle or disable action (e.g.,
call the existing toggleNotifications(), setNotificationsEnabled(false), or
props.onToggleNotifications() used elsewhere in Chat/index.tsx), or if no such
handler exists, remove or conditionally hide the '알림 끄기' menu item so it is not
shown to users.
🧹 Nitpick comments (1)
src/pages/Chat/index.tsx (1)

252-254: 타이포그래피 토큰 사용을 권장합니다.

text-[16px], text-[14px] 대신 text-sub1, text-body2 등 시맨틱 타이포그래피 유틸리티를 사용하면 일관성을 유지할 수 있습니다. As per coding guidelines, "Use semantic typography utilities (text-h1, text-body1, etc.) before custom styles".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Chat/index.tsx` around lines 252 - 254, The paragraph elements in
the Chat component use hardcoded size utilities (`text-[16px]` and
`text-[14px]`) which violates the typography token guideline; update the
className on the first <p> (currently using `text-[16px] font-bold`) to use the
semantic token `text-sub1` (and keep `font-bold` if needed) and update the
second <p> (currently `text-[14px]`) to use `text-body2` (or your project's
equivalent semantic token) so the component (leaveRoom modal JSX) uses semantic
typography utilities instead of custom pixel classes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/pages/Chat/index.tsx`:
- Around line 87-89: The useLongPress hook currently reads e.clientX/e.clientY
inside the setTimeout callback which can be invalidated; instead use the stored
coordinates in startPointRef.current when invoking onLongPress. Modify the timer
callback code in useLongPress (the block that sets timerRef.current and
didLongPressRef.current) to check startPointRef.current and call
onLongPress(startPointRef.current.x, startPointRef.current.y), then call
clearTimer(); ensure you keep references to timerRef, didLongPressRef,
startPointRef, onLongPress and clearTimer unchanged elsewhere.
- Around line 267-275: The click handler clears leaveRoom before checking it, so
deleteChatRoom never runs; capture the current room into a local variable (e.g.,
const room = leaveRoom) or check leaveRoom before calling setLeaveRoom(null),
then if room exists call await deleteChatRoom(room.roomId) inside the try/catch
and only after successful (or attempted) deletion call setLeaveRoom(null);
update the onClick handler that references setLeaveRoom, leaveRoom, and
deleteChatRoom accordingly.

---

Duplicate comments:
In `@src/pages/Chat/index.tsx`:
- Line 324: The menu entry with label '알림 끄기' currently has an empty onClick (()
=> {}) which makes it nonfunctional; replace the empty handler with the real
notification toggle or disable action (e.g., call the existing
toggleNotifications(), setNotificationsEnabled(false), or
props.onToggleNotifications() used elsewhere in Chat/index.tsx), or if no such
handler exists, remove or conditionally hide the '알림 끄기' menu item so it is not
shown to users.

---

Nitpick comments:
In `@src/pages/Chat/index.tsx`:
- Around line 252-254: The paragraph elements in the Chat component use
hardcoded size utilities (`text-[16px]` and `text-[14px]`) which violates the
typography token guideline; update the className on the first <p> (currently
using `text-[16px] font-bold`) to use the semantic token `text-sub1` (and keep
`font-bold` if needed) and update the second <p> (currently `text-[14px]`) to
use `text-body2` (or your project's equivalent semantic token) so the component
(leaveRoom modal JSX) uses semantic typography utilities instead of custom pixel
classes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aa8166e1-9dc8-426d-9dbd-65189df0f771

📥 Commits

Reviewing files that changed from the base of the PR and between 2d00b80 and b50d285.

📒 Files selected for processing (2)
  • src/pages/Chat/components/ChatRoomContextMenu.tsx
  • src/pages/Chat/index.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/pages/Chat/components/ChatRoomContextMenu.tsx

Comment on lines +87 to +89
const longPress = useLongPress({
onLongPress: (x: number, y: number) => onLongPress(x, y, room),
});
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# useLongPress 훅의 setTimeout 콜백 확인
cat src/utils/hooks/useLongPress.ts

Repository: BCSDLab/KONECT_FRONT_END

Length of output: 2291


useLongPress 훅의 이벤트 객체 참조 버그

setTimeout 콜백에서 e.clientX/e.clientY를 직접 참조하는 것은 위험합니다. 이벤트 핸들러 반환 후 React의 이벤트 객체가 무효화되므로 좌표가 NaN이 됩니다. 이미 저장된 startPointRef.current.x/y를 사용하도록 수정하세요:

timerRef.current = setTimeout(() => {
  didLongPressRef.current = true;
  if (startPointRef.current) {
    onLongPress(startPointRef.current.x, startPointRef.current.y);
  }
  clearTimer();
}, delay);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Chat/index.tsx` around lines 87 - 89, The useLongPress hook
currently reads e.clientX/e.clientY inside the setTimeout callback which can be
invalidated; instead use the stored coordinates in startPointRef.current when
invoking onLongPress. Modify the timer callback code in useLongPress (the block
that sets timerRef.current and didLongPressRef.current) to check
startPointRef.current and call onLongPress(startPointRef.current.x,
startPointRef.current.y), then call clearTimer(); ensure you keep references to
timerRef, didLongPressRef, startPointRef, onLongPress and clearTimer unchanged
elsewhere.

Comment on lines +267 to +275
onClick={async () => {
setLeaveRoom(null);
if (!leaveRoom) return;
try {
await deleteChatRoom(leaveRoom.roomId);
} catch (error) {
console.error('Error leaving chat room:', error);
}
}}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

leaveRoom을 null로 설정한 후 사용하고 있어 삭제가 실행되지 않습니다.

Line 268에서 setLeaveRoom(null) 호출 후 Line 269에서 leaveRoom을 체크하면 항상 null이므로 deleteChatRoom이 호출되지 않습니다.

🐛 수정 예시
             onClick={async () => {
-              setLeaveRoom(null);
               if (!leaveRoom) return;
+              const roomId = leaveRoom.roomId;
+              setLeaveRoom(null);
               try {
-                await deleteChatRoom(leaveRoom.roomId);
+                await deleteChatRoom(roomId);
               } catch (error) {
                 console.error('Error leaving chat room:', error);
               }
             }}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/pages/Chat/index.tsx` around lines 267 - 275, The click handler clears
leaveRoom before checking it, so deleteChatRoom never runs; capture the current
room into a local variable (e.g., const room = leaveRoom) or check leaveRoom
before calling setLeaveRoom(null), then if room exists call await
deleteChatRoom(room.roomId) inside the try/catch and only after successful (or
attempted) deletion call setLeaveRoom(null); update the onClick handler that
references setLeaveRoom, leaveRoom, and deleteChatRoom accordingly.

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.

[feat] 채팅방 삭제 및 이름 변경 기능 추가

2 participants