Skip to content

Conversation

@hamxxn
Copy link
Collaborator

@hamxxn hamxxn commented Dec 13, 2025

📌 Related Issues

✅ 체크 리스트

  • PR 제목의 형식을 잘 작성했나요? e.g. [Feat/#이슈번호] PR 템플릿 작성
  • 빌드가 성공했나요? (pnpm build)
  • 컨벤션을 지켰나요?
  • 이슈는 등록했나요?
  • 리뷰어와 라벨을 지정했나요?

📄 Tasks

/chat-rooms api 연동(get)

/chat-rooms api 연동(post)

/chat-rooms api 연동(patch)

⭐ PR Point (To Reviewer)

서버에서 목업 올려주시면 ui까지 마무리 할게요!

Summary by CodeRabbit

릴리스 노트

  • New Features

    • 채팅 목록이 이제 실제 서버 데이터를 기반으로 로드됩니다.
    • 채팅방 메타데이터에 음식점 및 사용자 정보가 추가되었습니다.
  • Refactor

    • 채팅 관련 컴포넌트의 속성명을 더욱 명확하고 일관성 있게 개선했습니다.
    • 로컬 모의 데이터를 제거하고 실제 API 연동으로 전환했습니다.
  • Documentation

    • 예약 운영 시간 형식을 HH:MM-HH:MM으로 업데이트하고 문서화했습니다.

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

@hamxxn hamxxn self-assigned this Dec 13, 2025
@hamxxn hamxxn requested a review from holdn2 as a code owner December 13, 2025 03:56
@coderabbitai
Copy link

coderabbitai bot commented Dec 13, 2025

Walkthrough

채팅 목록 페이지를 모의 데이터에서 실제 API 연동으로 전환했습니다. 새로운 API 모듈을 추가하고, 컴포넌트 props 이름을 표준화하며, React Query를 통해 데이터 페칭, 캐싱, 무효화 기능을 구현했습니다.

Changes

Cohort / File(s) Summary
API 데이터 계약 업데이트
apis/data-contracts.ts
FoodTruckDetailResponse.regionCodes의 타입을 number[]에서 RegionResponse[]로 변경; ChatRoomMetaDataResponsefoodTruckIdmemberId 필드 추가; operationHour 포맷을 HH:MM~HH:MM에서 HH:MM-HH:MM으로 업데이트
채팅 목록 API 모듈
src/pages/chat-list/api/chat-list-api.ts
새 파일 추가: 채팅 목록 조회/생성/읽음 표시를 위한 HTTP 래퍼 함수 및 React Query 훅(useGetChatList, usePostChatRoom, usePatchChatRoom) 구현
채팅 목록 페이지 및 훅
src/pages/chat-list/ChatList.tsx, src/pages/chat-list/hooks/use-chat-list.tsx
모의 데이터 제거 및 useGetChatList API 훅으로 대체; 로딩/에러 상태 처리 추가; props 이름 표준화 적용; hook에서 chatList 반환 제거
모의 데이터 정리
src/pages/chat-list/constant/mocks.ts, src/pages/chat-list/types/chat-list-type.ts
모의 데이터 배열과 Chat 인터페이스 제거
채팅 목록 항목 컴포넌트 Props 통일
src/shared/components/chat/chat-list-item/ChatListItem.tsx, src/shared/components/chat/chat-list-item/ChatListItem.stories.tsx
Props 이름 표준화: profileImageprofileImageUrl, clientNamename, tagTitlefoodTruckName, lastChatlastMessage, lastChatTimelastMessageSendTime

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

  • 중점 검토 영역:
    • API 응답 데이터 구조와 컴포넌트 매핑의 일관성 확인
    • React Query 무효화 전략이 모든 뮤테이션에서 올바르게 적용되었는지 검증
    • Props 이름 변경이 모든 사용처(ChatList, ChatListItem, Storybook)에서 일관되게 적용되었는지 확인
    • 로딩/에러 상태 UI 처리의 완전성 (TODO 주석 확인)

Possibly related PRs

Suggested reviewers

  • Glyph8
  • junghyungo

Poem

🐰 Chat list 춤을 춘다네, API와 손잡고,
Mock 데이터는 안녕, 진짜 데이터 환영해!
Props는 깔끔하게, Query는 똑똑하게,
Loading에 Error까지, 모두 준비 완료! 🚀

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings, 1 inconclusive)
Check name Status Explanation Resolution
Title check ⚠️ Warning 제목이 주요 변경 사항(chat api 연동)을 명확하게 반영하고 있으나, 검토 완료 전임을 나타내는 '아직 리뷰 x'는 PR 제목으로 부적절합니다. [Feature/#207] chat api 연동으로 수정하여 검토 상태 표기를 제거하고 명확한 기능 설명만 포함하도록 합니다.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive PR 설명이 템플릿을 따르고 있지만, Tasks 섹션이 완성되지 않았으며 체크리스트가 모두 미완료 상태입니다. Tasks 섹션에 각 API 연동의 구체적인 구현 내용을 작성하고, 빌드 성공 및 컨벤션 준수 여부를 체크리스트에 표시해주시기 바랍니다.
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed PR의 코드 변경 사항이 issue #207의 모든 요구 사항(GET, POST, PATCH API 연동)을 충족합니다.
Out of Scope Changes check ✅ Passed 모든 코드 변경 사항이 issue #207의 chat API 연동 범위 내에 있으며, 관련 없는 수정 사항은 없습니다.
✨ 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 feature/#207/chat-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

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

@github-actions
Copy link

빌드 및 린트 결과

일부 검사 실패 ⚠️

  • 린트 실패 ❌
  • 빌드 실패 ❌

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

🧹 Nitpick comments (2)
src/pages/chat-list/ChatList.tsx (2)

16-18: isOwner 구분 로직 구현이 필요합니다.

TODO 주석에서 언급했듯이 사용자/오너 구분 로직이 필요합니다. 현재 true로 하드코딩되어 있어 일반 사용자의 채팅 목록을 볼 수 없습니다.

사용자 역할을 확인하는 로직 구현을 도와드릴까요? 예를 들어 사용자 컨텍스트나 인증 상태에서 역할을 가져오는 방법이 있습니다.


34-39: 에러 처리 개선이 필요합니다.

현재 에러 처리가 단순한 텍스트 메시지만 표시합니다. 사용자 경험 향상을 위해 재시도 버튼이나 더 나은 에러 UI를 제공하는 것이 좋습니다.

에러 상태를 처리하는 공통 컴포넌트나 재시도 로직 추가를 고려하세요:

if (isError) {
  return (
    <div className="flex flex-col items-center justify-center p-8">
      <p className="text-grayscale-700 mb-4">
        채팅 목록을 불러오는 중에 오류가 발생했습니다.
      </p>
      <Button onClick={() => refetch()}>다시 시도</Button>
    </div>
  );
}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 082b2f6 and c1ba1e7.

📒 Files selected for processing (7)
  • apis/data-contracts.ts (4 hunks)
  • src/pages/chat-list/ChatList.tsx (3 hunks)
  • src/pages/chat-list/api/chat-list-api.ts (1 hunks)
  • src/pages/chat-list/constant/mocks.ts (0 hunks)
  • src/pages/chat-list/hooks/use-chat-list.tsx (1 hunks)
  • src/pages/chat-list/types/chat-list-type.ts (0 hunks)
  • src/shared/components/chat/chat-list-item/ChatListItem.tsx (3 hunks)
💤 Files with no reviewable changes (2)
  • src/pages/chat-list/constant/mocks.ts
  • src/pages/chat-list/types/chat-list-type.ts
🧰 Additional context used
🧬 Code graph analysis (3)
src/pages/chat-list/api/chat-list-api.ts (3)
src/api/apiRequest.ts (1)
  • apiRequest (28-126)
apis/data-contracts.ts (3)
  • GetChatRoomsData (1794-1794)
  • CreateChatRoomData (1796-1796)
  • MarkMessagesAsReadData (1813-1813)
src/shared/querykey/user-info.ts (1)
  • USER_INFO (1-14)
src/shared/components/chat/chat-list-item/ChatListItem.tsx (1)
src/shared/components/ui/tag/Tag.tsx (1)
  • Tag (5-11)
src/pages/chat-list/ChatList.tsx (3)
src/pages/chat-list/api/chat-list-api.ts (1)
  • useGetChatList (40-45)
src/shared/components/layout/loading/Loading.tsx (1)
  • Loading (7-13)
src/shared/components/chat/chat-list-item/ChatListItem.tsx (1)
  • ChatListItem (17-93)
🪛 GitHub Actions: ci
src/pages/chat-list/api/chat-list-api.ts

[error] 42-42: The following dependencies are missing in your queryKey: isOwner @tanstack/query/exhaustive-deps

🪛 GitHub Check: build
src/pages/chat-list/api/chat-list-api.ts

[failure] 42-42:
The following dependencies are missing in your queryKey: isOwner

🔇 Additional comments (5)
src/pages/chat-list/hooks/use-chat-list.tsx (1)

1-49: 목 데이터 제거가 깔끔하게 처리되었습니다.

실제 API 데이터 사용을 위해 로컬 상태와 목 데이터 로직이 제거되었고, 이제 UI 상태 관리만 담당합니다.

apis/data-contracts.ts (3)

1689-1706: 채팅방 메타데이터에 새 필드가 추가되었습니다.

ChatRoomMetaDataResponsefoodTruckIdmemberId 필드가 추가되었습니다. 이 변경사항은 채팅 관련 기능에서 활용 가능합니다.


1464-1465: 지역 코드 타입 변경은 이미 완벽하게 구현되었습니다.

regionCodes의 타입 변경(단순 숫자 배열 → RegionResponse[])은 전체 코드베이스에서 일관되게 적용되어 있습니다. 모든 사용처가 올바르게 업데이트되었으며, 스키마 검증, 훅, 컴포넌트 모두 RegionResponse 구조의 code, name 등의 속성을 제대로 처리하고 있습니다.

Likely an incorrect or invalid review comment.


386-390: 운영 시간 형식 변경은 백엔드 API 계약 변경으로 확인됩니다.

apis/data-contracts.ts는 Swagger에서 자동 생성되는 파일이며, 운영 시간 형식이 HH:MM ~ HH:MM에서 HH:MM-HH:MM로 변경되었습니다. 이는 백엔드 API 스펙 변경이 반영된 것이며, 프론트엔드 코드는 이 필드를 파싱하지 않으므로 추가 조정이 필요하지 않습니다.

src/shared/components/chat/chat-list-item/ChatListItem.tsx (1)

5-27: Props 이름이 API 응답 구조에 맞게 명확하게 개선되었습니다.

기존 prop 이름들이 더 명확하고 API 응답과 일치하도록 업데이트되었습니다:

  • clientNamename
  • tagTitlefoodTruckName
  • lastChatlastMessage
  • lastChatTimelastMessageSendTime

모든 사용처가 일관되게 업데이트되었습니다.

Comment on lines +21 to +30
const postChatRoom = async (foodTruckId: number) => {
const response = await apiRequest<CreateChatRoomData>({
endPoint: '/chat/rooms',
method: 'POST',
params: {
foodTruckId,
},
});
return response.data;
};
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

foodTruckId를 요청 바디에 포함해야 합니다.

CreateChatRoomRequest 인터페이스에 따르면 foodTruckId는 요청 바디에 포함되어야 하는데, 현재 쿼리 파라미터로 전달되고 있습니다.

다음과 같이 수정하세요:

 const postChatRoom = async (foodTruckId: number) => {
   const response = await apiRequest<CreateChatRoomData>({
     endPoint: '/chat/rooms',
     method: 'POST',
-    params: {
+    data: {
       foodTruckId,
     },
   });
   return response.data;
 };
📝 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
const postChatRoom = async (foodTruckId: number) => {
const response = await apiRequest<CreateChatRoomData>({
endPoint: '/chat/rooms',
method: 'POST',
params: {
foodTruckId,
},
});
return response.data;
};
const postChatRoom = async (foodTruckId: number) => {
const response = await apiRequest<CreateChatRoomData>({
endPoint: '/chat/rooms',
method: 'POST',
data: {
foodTruckId,
},
});
return response.data;
};
🤖 Prompt for AI Agents
In src/pages/chat-list/api/chat-list-api.ts around lines 21 to 30, the function
posts foodTruckId as query params but the CreateChatRoomRequest expects it in
the request body; update postChatRoom to send { foodTruckId } in the request
body (e.g., the apiRequest "data" or "body" property) instead of params, and
keep the function return type the same (response.data) so the request payload
matches the CreateChatRoomRequest interface.

Comment on lines +47 to +55
export const usePostChatRoom = (foodTruckId: number) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: () => postChatRoom(foodTruckId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS() });
},
});
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

mutation 함수가 유연하지 않습니다.

foodTruckId가 훅 생성 시점에 고정되어, 서로 다른 푸드트럭에 대해 여러 채팅방을 생성하려면 훅을 여러 번 호출해야 합니다. mutation 함수가 foodTruckId를 인자로 받도록 변경하는 것이 더 유연합니다.

다음과 같이 리팩토링을 권장합니다:

-export const usePostChatRoom = (foodTruckId: number) => {
+export const usePostChatRoom = () => {
   const queryClient = useQueryClient();
   return useMutation({
-    mutationFn: () => postChatRoom(foodTruckId),
+    mutationFn: (foodTruckId: number) => postChatRoom(foodTruckId),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS() });
     },
   });
 };

사용 예시:

const { mutate } = usePostChatRoom();
mutate(foodTruckId);
🤖 Prompt for AI Agents
In src/pages/chat-list/api/chat-list-api.ts around lines 47 to 55, the hook
currently captures foodTruckId at creation time which makes it inflexible;
change the hook to not accept foodTruckId and instead make the mutation function
accept an id parameter (e.g., mutationFn: (id: number) => postChatRoom(id)) so
callers can call mutate(foodTruckId). Keep onSuccess logic the same (invalidate
USER_INFO.CHATS()) and update any call sites to call usePostChatRoom() without
args and pass the foodTruckId into mutate.

Comment on lines +57 to +65
export const usePatchChatRoom = (chatRoomId: number) => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: () => patchChatRoom(chatRoomId),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS() });
},
});
};
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

mutation 함수가 유연하지 않습니다.

chatRoomId가 훅 생성 시점에 고정되어, 서로 다른 채팅방에 대해 읽음 표시를 하려면 훅을 여러 번 호출해야 합니다. mutation 함수가 chatRoomId를 인자로 받도록 변경하는 것이 더 유연합니다.

다음과 같이 리팩토링을 권장합니다:

-export const usePatchChatRoom = (chatRoomId: number) => {
+export const usePatchChatRoom = () => {
   const queryClient = useQueryClient();
   return useMutation({
-    mutationFn: () => patchChatRoom(chatRoomId),
+    mutationFn: (chatRoomId: number) => patchChatRoom(chatRoomId),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS() });
     },
   });
 };

사용 예시:

const { mutate } = usePatchChatRoom();
mutate(chatRoomId);
🤖 Prompt for AI Agents
In src/pages/chat-list/api/chat-list-api.ts around lines 57 to 65, the hook
binds chatRoomId at creation time making it inflexible; change the hook to
accept no chatRoomId and make the mutation function take chatRoomId as an
argument (so callers call mutate(chatRoomId)). Update useMutation to use a
mutationFn that accepts the id parameter and adjust TypeScript generics/types
accordingly; keep the onSuccess handler the same and continue invalidating
USER_INFO.CHATS().

Comment on lines 87 to +96
<ChatListItem
key={item.clientId}
key={item.id}
isEditing={isEditing}
clientName={item.clientName}
tagTitle={item.tagTitle}
lastChat={item.lastChat}
lastChatTime={item.lastChatTime}
unreadCount={item.unreadCount}
isChecked={selectChatList.has(item.clientId)}
handleCheckChange={() => handleCheckChange(item.clientId)}
name={item.name ?? ''}
foodTruckName={item.foodTruckName ?? ''}
lastMessage={item.lastMessage ?? ''}
lastMessageSendTime={item.lastMessageSendTime ?? ''}
unreadCount={item.unreadCount ?? 0}
isChecked={selectChatList.has(item.id ?? 0)}
handleCheckChange={() => handleCheckChange(item.id ?? 0)}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

profileImageUrl prop이 누락되었고 item.id 기본값 처리를 개선하세요.

  1. ChatListItemprofileImageUrl prop을 기대하지만 전달되지 않고 있습니다.
  2. item.id ?? 0을 사용하면 실제로 id가 없는 항목이 id가 0인 항목처럼 처리되어 Set 연산에서 문제가 발생할 수 있습니다.

다음과 같이 수정하세요:

         {(chatListData?.content ?? []).map(item => {
+          if (!item.id) {
+            console.warn('Chat item missing id:', item);
+            return null;
+          }
           return (
             <ChatListItem
               key={item.id}
+              profileImageUrl={item.profileImageUrl}
               isEditing={isEditing}
               name={item.name ?? ''}
               foodTruckName={item.foodTruckName ?? ''}
               lastMessage={item.lastMessage ?? ''}
               lastMessageSendTime={item.lastMessageSendTime ?? ''}
               unreadCount={item.unreadCount ?? 0}
-              isChecked={selectChatList.has(item.id ?? 0)}
-              handleCheckChange={() => handleCheckChange(item.id ?? 0)}
+              isChecked={selectChatList.has(item.id)}
+              handleCheckChange={() => handleCheckChange(item.id)}
             />
           );
         })}

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/pages/chat-list/ChatList.tsx around lines 87 to 96, the ChatListItem is
missing the profileImageUrl prop and uses item.id ?? 0 which can conflate
undefined ids with a real id of 0; add profileImageUrl by passing
item.profileImageUrl ?? '' to the component and stop defaulting id to 0 —
instead compute a local const id = item.id; if id == null skip rendering this
item (or otherwise handle it upstream) and use that id for
selectChatList.has(id) and handleCheckChange(() => handleCheckChange(id)); this
ensures profile images are passed and prevents accidental collisions from a
falsy numeric default.

@github-actions
Copy link

빌드 및 린트 결과

일부 검사 실패 ⚠️

  • 린트 통과 ✅
  • 빌드 실패 ❌

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

Caution

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

⚠️ Outside diff range comments (1)
src/shared/components/chat/chat-list-item/ChatListItem.stories.tsx (1)

13-37: foodTruckName 설명이 의미와 불일치할 수 있어요(문서/자동독스 혼란)
foodTruckName인데 description이 “고객에게 붙은 태그”로 되어 있어, Storybook autodocs에서 의미가 헷갈릴 수 있습니다. 실제 의도가 “푸드트럭 이름”이면 설명을 맞추고, “태그”가 맞다면 prop 명을 재검토해 주세요.

♻️ Duplicate comments (3)
src/pages/chat-list/api/chat-list-api.ts (3)

47-55: mutation 함수가 유연하지 않습니다.

foodTruckId가 훅 생성 시점에 고정되어, 다른 푸드트럭에 대해 채팅방을 생성하려면 훅을 여러 번 호출해야 합니다.

다음과 같이 리팩토링을 권장합니다:

-export const usePostChatRoom = (foodTruckId: number, isOwner: boolean) => {
+export const usePostChatRoom = (isOwner: boolean) => {
   const queryClient = useQueryClient();
   return useMutation({
-    mutationFn: () => postChatRoom(foodTruckId),
+    mutationFn: (foodTruckId: number) => postChatRoom(foodTruckId),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS(isOwner) });
     },
   });
 };

사용 예시:

const { mutate } = usePostChatRoom(isOwner);
mutate(foodTruckId);

57-65: mutation 함수가 유연하지 않습니다.

chatRoomId가 훅 생성 시점에 고정되어, 다른 채팅방에 대해 읽음 표시를 하려면 훅을 여러 번 호출해야 합니다.

다음과 같이 리팩토링을 권장합니다:

-export const usePatchChatRoom = (chatRoomId: number, isOwner: boolean) => {
+export const usePatchChatRoom = (isOwner: boolean) => {
   const queryClient = useQueryClient();
   return useMutation({
-    mutationFn: () => patchChatRoom(chatRoomId),
+    mutationFn: (chatRoomId: number) => patchChatRoom(chatRoomId),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS(isOwner) });
     },
   });
 };

사용 예시:

const { mutate } = usePatchChatRoom(isOwner);
mutate(chatRoomId);

21-30: foodTruckId를 요청 바디에 포함해야 합니다.

POST 요청에서 foodTruckId가 쿼리 파라미터(params)로 전달되고 있지만, 요청 바디(data)에 포함되어야 합니다.

다음과 같이 수정하세요:

 const postChatRoom = async (foodTruckId: number) => {
   const response = await apiRequest<CreateChatRoomData>({
     endPoint: '/chat/rooms',
     method: 'POST',
-    params: {
+    data: {
       foodTruckId,
     },
   });
   return response.data;
 };
🧹 Nitpick comments (1)
src/pages/chat-list/api/chat-list-api.ts (1)

40-45: 불필요한 스프레드 연산자를 제거하세요.

USER_INFO.CHATS(isOwner)가 이미 배열을 반환하므로, 스프레드 연산자와 배열 래핑이 불필요합니다.

다음과 같이 수정할 수 있습니다:

 export const useGetChatList = (isOwner: boolean) => {
   return useQuery({
-    queryKey: [...USER_INFO.CHATS(isOwner)],
+    queryKey: USER_INFO.CHATS(isOwner),
     queryFn: () => getChatList(isOwner),
   });
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c1ba1e7 and 30710de.

📒 Files selected for processing (3)
  • src/pages/chat-list/api/chat-list-api.ts (1 hunks)
  • src/shared/components/chat/chat-list-item/ChatListItem.stories.tsx (4 hunks)
  • src/shared/querykey/user-info.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/chat-list/api/chat-list-api.ts (3)
src/api/apiRequest.ts (1)
  • apiRequest (28-126)
apis/data-contracts.ts (3)
  • GetChatRoomsData (1794-1794)
  • CreateChatRoomData (1796-1796)
  • MarkMessagesAsReadData (1813-1813)
src/shared/querykey/user-info.ts (1)
  • USER_INFO (1-17)
🔇 Additional comments (7)
src/shared/components/chat/chat-list-item/ChatListItem.stories.tsx (4)

56-63: 기본 args 리네이밍 적용은 깔끔합니다
profileImageUrl/name/foodTruckName/lastMessageSendTime로 기본값이 잘 정리되어, 각 스토리에서 중복이 줄었습니다.


65-71: Default/Read 스토리에서 lastMessage로 통일된 점 좋습니다
리네이밍된 lastMessage가 각 스토리에 일관되게 반영되어 있습니다.

Also applies to: 73-79


81-89: LongText 케이스 유지 좋고, name 길이 스트레스 테스트 목적도 명확합니다
긴 이름/메시지 케이스가 리네이밍 이후에도 유지되어 UI 회귀 확인에 도움이 됩니다.


91-98: NoProfileImage: 빈 문자열 처리 케이스 유지 확인만 해주세요
스토리에서 profileImageUrl: ''로 케이스를 잘 잡았고, 컴포넌트가 빈 문자열을 “이미지 없음”으로 처리하는지만 확인하면 됩니다.

src/shared/querykey/user-info.ts (1)

5-9: isOwner 기반 쿼리 키 구조가 적절합니다.

채팅 목록을 소유자/비소유자 관점으로 구분하여 캐싱할 수 있도록 쿼리 키가 올바르게 구성되었습니다.

src/pages/chat-list/api/chat-list-api.ts (2)

10-19: 채팅 목록 조회 API가 올바르게 구현되었습니다.

isOwner 파라미터를 쿼리 파라미터로 전달하여 소유자/비소유자 관점의 채팅 목록을 조회하는 구조가 적절합니다.


32-38: 읽음 표시 API가 올바르게 구현되었습니다.

chatRoomId를 URL 경로에 포함하여 PATCH 요청을 보내는 구조가 적절합니다.

@github-actions
Copy link

빌드 및 린트 결과

모든 검사 통과 🎉

  • 린트 통과 ✅
  • 빌드 성공 🎊

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

♻️ Duplicate comments (3)
src/pages/chat-list/api/chat-list-api.ts (3)

48-56: mutation 함수를 더 유연하게 만드는 것을 권장합니다.

foodTruckId가 훅 생성 시점에 고정되어 있습니다. 여러 푸드트럭에 대해 채팅방을 생성하려면 훅을 여러 번 호출해야 합니다. mutation 함수가 foodTruckId를 인자로 받도록 변경하면 더 유연하게 사용할 수 있습니다.

다음과 같이 리팩토링할 수 있습니다:

-export const usePostChatRoom = (foodTruckId: number) => {
+export const usePostChatRoom = () => {
   const queryClient = useQueryClient();
   return useMutation({
-    mutationFn: () => postChatRoom(foodTruckId),
+    mutationFn: (foodTruckId: number) => postChatRoom(foodTruckId),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS() });
     },
   });
 };

사용 예시:

const { mutate } = usePostChatRoom();
mutate(foodTruckId);

58-66: mutation 함수를 더 유연하게 만드는 것을 권장합니다.

chatRoomId가 훅 생성 시점에 고정되어 있습니다. 여러 채팅방에 대해 읽음 표시를 하려면 훅을 여러 번 호출해야 합니다. mutation 함수가 chatRoomId를 인자로 받도록 변경하면 더 유연하게 사용할 수 있습니다.

다음과 같이 리팩토링할 수 있습니다:

-export const usePatchChatRoom = (chatRoomId: number) => {
+export const usePatchChatRoom = () => {
   const queryClient = useQueryClient();
   return useMutation({
-    mutationFn: () => patchChatRoom(chatRoomId),
+    mutationFn: (chatRoomId: number) => patchChatRoom(chatRoomId),
     onSuccess: () => {
       queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS() });
     },
   });
 };

사용 예시:

const { mutate } = usePatchChatRoom();
mutate(chatRoomId);

21-30: foodTruckId를 요청 바디에 포함해야 합니다.

POST 요청에서 params는 쿼리 파라미터로 전달됩니다. CreateChatRoomRequest 인터페이스에 따르면 foodTruckId는 요청 바디에 포함되어야 합니다.

다음과 같이 수정하세요:

 const postChatRoom = async (foodTruckId: number) => {
   const response = await apiRequest<CreateChatRoomData>({
     endPoint: '/chat/rooms',
     method: 'POST',
-    params: {
+    data: {
       foodTruckId,
     },
   });
   return response.data;
 };
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 30710de and b4a97a7.

📒 Files selected for processing (1)
  • src/pages/chat-list/api/chat-list-api.ts (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/pages/chat-list/api/chat-list-api.ts (3)
src/api/apiRequest.ts (1)
  • apiRequest (28-126)
apis/data-contracts.ts (3)
  • GetChatRoomsData (1794-1794)
  • CreateChatRoomData (1796-1796)
  • MarkMessagesAsReadData (1813-1813)
src/shared/querykey/user-info.ts (1)
  • USER_INFO (1-14)

Comment on lines +40 to +46
export const useGetChatList = (isOwner: boolean) => {
return useQuery({
// eslint-disable-next-line @tanstack/query/exhaustive-deps
queryKey: USER_INFO.CHATS(),
queryFn: () => getChatList(isOwner),
});
};
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

queryKey에 isOwner를 포함해야 합니다.

isOwner 값에 따라 다른 데이터를 가져오지만 queryKey에 이 의존성이 누락되어 있습니다. ESLint 경고를 비활성화하는 것은 문제를 해결하지 않습니다. 이로 인해 isOwner 값이 다른 호출 간에 잘못된 캐시 데이터가 반환될 수 있습니다.

예: useGetChatList(true) 호출 후 useGetChatList(false)를 호출하면, 두 번째 호출이 첫 번째 호출의 캐시된 데이터를 반환합니다.

다음과 같이 수정하세요:

 export const useGetChatList = (isOwner: boolean) => {
   return useQuery({
-    // eslint-disable-next-line @tanstack/query/exhaustive-deps
-    queryKey: USER_INFO.CHATS(),
+    queryKey: [...USER_INFO.CHATS(), isOwner],
     queryFn: () => getChatList(isOwner),
   });
 };
📝 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
export const useGetChatList = (isOwner: boolean) => {
return useQuery({
// eslint-disable-next-line @tanstack/query/exhaustive-deps
queryKey: USER_INFO.CHATS(),
queryFn: () => getChatList(isOwner),
});
};
export const useGetChatList = (isOwner: boolean) => {
return useQuery({
queryKey: [...USER_INFO.CHATS(), isOwner],
queryFn: () => getChatList(isOwner),
});
};
🤖 Prompt for AI Agents
In src/pages/chat-list/api/chat-list-api.ts around lines 40 to 46, the queryKey
for useGetChatList omits the isOwner dependency causing cache collisions;
include isOwner in the queryKey (e.g., USER_INFO.CHATS(isOwner) or
[USER_INFO.CHATS(), isOwner]) so React Query caches per isOwner value, remove
the eslint-disable comment, and keep the queryFn as getChatList(isOwner) to
ensure correct keyed caching.

unreadCount={item.unreadCount}
isChecked={selectChatList.has(item.clientId)}
handleCheckChange={() => handleCheckChange(item.clientId)}
name={item.name ?? ''}
Copy link
Collaborator

Choose a reason for hiding this comment

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

null 예외처리를 빈 문자열 대신 '로딩중', '알 수 없음' 등은 어떨까요?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] 채팅 api 연동

3 participants