diff --git a/apis/data-contracts.ts b/apis/data-contracts.ts
index 21b7d865..feb4d50b 100644
--- a/apis/data-contracts.ts
+++ b/apis/data-contracts.ts
@@ -383,10 +383,10 @@ export interface CreateReservationRequest {
*/
reservationDates: string[];
/**
- * 운영 시간 (형식: HH:MM ~ HH:MM)
+ * 운영 시간 (형식: HH:MM-HH:MM)
* @minLength 1
- * @pattern ^([01]\d|2[0-3]):([0-5]\d) ~ ([01]\d|2[0-3]):([0-5]\d)$
- * @example "15:00 ~ 16:00"
+ * @pattern ^([01]\d|2[0-3]):([0-5]\d)-([01]\d|2[0-3]):([0-5]\d)$
+ * @example "15:00-16:00"
*/
operationHour: string;
/**
@@ -788,8 +788,8 @@ export interface ReservationResponse {
*/
reservationDates?: string[];
/**
- * 운영 시간 (형식: HH:MM ~ HH:MM)
- * @example "15:00 ~ 16:00"
+ * 운영 시간 (형식: HH:MM-HH:MM)
+ * @example "15:00-16:00"
*/
operationHour?: string;
/**
@@ -1461,11 +1461,8 @@ export interface FoodTruckDetailResponse {
* @example "서울 광진구, 서울 강남구, 서울 영등포구"
*/
serviceAreas?: string;
- /**
- * 호출 가능 지역 코드
- * @example [1,2]
- */
- regionCodes?: number[];
+ /** 호출 가능 지역 정보 리스트 */
+ regionCodes?: RegionResponse[];
/**
* 푸드트럭 메뉴 카테고리 (라벨 리스트)
* @example ["한식","분식"]
@@ -1689,12 +1686,24 @@ export interface ChatRoomMetaDataResponse {
* @example "맛있는푸드트럭"
*/
foodTruckName?: string;
+ /**
+ * 푸드트럭 식별자
+ * @format int64
+ * @example 1
+ */
+ foodTruckId?: number;
/**
* 채팅방과 관련된 예약 ID (있는 경우: ID 반환, 없는 경우: null)
* @format int64
* @example 1
*/
reservationId?: number;
+ /**
+ * 예약자(일반 유저) 식별자
+ * @format int64
+ * @example 2
+ */
+ memberId?: number;
}
export interface BaseResponseListChatMessageResponse {
diff --git a/src/pages/chat-list/ChatList.tsx b/src/pages/chat-list/ChatList.tsx
index e8fa3075..1f21adde 100644
--- a/src/pages/chat-list/ChatList.tsx
+++ b/src/pages/chat-list/ChatList.tsx
@@ -6,16 +6,21 @@ import { Icon } from '@icon/Icon';
import OverlayModal from '@layout/overlay/Overlay';
import Navigation from '@layout/navigation/Navigation';
import Button from '@ui/button/Button';
+import { useGetChatList } from '@pages/chat-list/api/chat-list-api';
+import Loading from '@layout/loading/Loading';
export default function ChatList() {
const navigate = useNavigate();
const handleClickBack = () => navigate(-1);
+ //TODO: 유저,오너 구분 확인 로직 필요
+ const isOwner = true;
+ const { data: chatListData, isPending, isError } = useGetChatList(isOwner);
+
const {
isEditing,
activeFilter,
setActiveFilter,
- chatList,
selectChatList,
handleToggleEdit,
handleCheckChange,
@@ -25,6 +30,13 @@ export default function ChatList() {
handleCloseModal,
} = useChatList();
+ //TODO: 에러 처리 필요
+ if (isPending) {
+ return ;
+ }
+ if (isError) {
+ return
채팅 목록을 불러오는 중에 오류가 발생했습니다.
;
+ }
return (
<>
-
- {(chatList ?? []).map(item => {
+
+ {(chatListData?.content ?? []).map(item => {
return (
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)}
/>
);
})}
diff --git a/src/pages/chat-list/api/chat-list-api.ts b/src/pages/chat-list/api/chat-list-api.ts
new file mode 100644
index 00000000..c64e2998
--- /dev/null
+++ b/src/pages/chat-list/api/chat-list-api.ts
@@ -0,0 +1,66 @@
+import { apiRequest } from '@api/apiRequest';
+import { USER_INFO } from '@shared/querykey/user-info';
+import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
+import type {
+ CreateChatRoomData,
+ GetChatRoomsData,
+ MarkMessagesAsReadData,
+} from 'apis/data-contracts';
+
+const getChatList = async (isOwner: boolean) => {
+ const response = await apiRequest({
+ endPoint: '/chat/rooms',
+ method: 'GET',
+ params: {
+ isOwner,
+ },
+ });
+ return response.data;
+};
+
+const postChatRoom = async (foodTruckId: number) => {
+ const response = await apiRequest({
+ endPoint: '/chat/rooms',
+ method: 'POST',
+ params: {
+ foodTruckId,
+ },
+ });
+ return response.data;
+};
+
+const patchChatRoom = async (chatRoomId: number) => {
+ const response = await apiRequest({
+ endPoint: `/chat/rooms/${chatRoomId}/read`,
+ method: 'PATCH',
+ });
+ return response.data;
+};
+
+export const useGetChatList = (isOwner: boolean) => {
+ return useQuery({
+ // eslint-disable-next-line @tanstack/query/exhaustive-deps
+ queryKey: USER_INFO.CHATS(),
+ queryFn: () => getChatList(isOwner),
+ });
+};
+
+export const usePostChatRoom = (foodTruckId: number) => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: () => postChatRoom(foodTruckId),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS() });
+ },
+ });
+};
+
+export const usePatchChatRoom = (chatRoomId: number) => {
+ const queryClient = useQueryClient();
+ return useMutation({
+ mutationFn: () => patchChatRoom(chatRoomId),
+ onSuccess: () => {
+ queryClient.invalidateQueries({ queryKey: USER_INFO.CHATS() });
+ },
+ });
+};
diff --git a/src/pages/chat-list/constant/mocks.ts b/src/pages/chat-list/constant/mocks.ts
deleted file mode 100644
index 5b7336d7..00000000
--- a/src/pages/chat-list/constant/mocks.ts
+++ /dev/null
@@ -1,77 +0,0 @@
-import type { Chat } from '@pages/chat-list/types/chat-list-type';
-
-export const mockup: Chat[] = [
- {
- clientId: 1,
- clientName: '고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat: '혹시 예약 가능할까요?',
- lastChatTime: '오후 5:40',
- unreadCount: 12,
- },
- {
- clientId: 2,
- clientName: '고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat: '혹시 예약 가능할까요?',
- lastChatTime: '오후 5:40',
- unreadCount: 122,
- },
- {
- clientId: 3,
- clientName: '고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat: '혹시 예약 가능할까요?',
- lastChatTime: '오후 5:40',
- unreadCount: 0,
- },
- {
- clientId: 4,
- clientName: '고객이름고객이름고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat:
- '혹시 예약 가능할까요? 아 안된다고요. 알겠습니다. 몇자 제한입니까',
- lastChatTime: '오후 5:40',
- unreadCount: 12,
- },
- {
- clientId: 5,
- clientName: '고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat: '혹시 예약 가능할까요?',
- lastChatTime: '오후 5:40',
- unreadCount: 0,
- },
- {
- clientId: 6,
- clientName: '고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat: '혹시 예약 가능할까요?',
- lastChatTime: '오후 5:40',
- unreadCount: 0,
- },
- {
- clientId: 7,
- clientName: '고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat: '혹시 예약 가능할까요?',
- lastChatTime: '오후 5:40',
- unreadCount: 0,
- },
- {
- clientId: 8,
- clientName: '고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat: '혹시 예약 가능할까요?',
- lastChatTime: '오후 5:40',
- unreadCount: 0,
- },
- {
- clientId: 9,
- clientName: '고객이름',
- tagTitle: '오소리 푸드트럭',
- lastChat: '혹시 예약 가능할까요?',
- lastChatTime: '오후 5:40',
- unreadCount: 0,
- },
-];
diff --git a/src/pages/chat-list/hooks/use-chat-list.tsx b/src/pages/chat-list/hooks/use-chat-list.tsx
index 2be5ef30..7df9f806 100644
--- a/src/pages/chat-list/hooks/use-chat-list.tsx
+++ b/src/pages/chat-list/hooks/use-chat-list.tsx
@@ -1,11 +1,9 @@
-import { mockup } from '@pages/chat-list/constant/mocks';
-import type { Chat } from '@pages/chat-list/types/chat-list-type';
-import { useEffect, useState } from 'react';
+import { useState } from 'react';
export const useChatList = () => {
const [isEditing, setIsEditing] = useState(false);
const [activeFilter, setActiveFilter] = useState('전체보기');
- const [chatList, setChatList] = useState([]);
+
const [selectChatList, setSelectChatList] = useState(new Set());
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState(false);
@@ -36,16 +34,10 @@ export const useChatList = () => {
const handleCloseModal = () => setIsDeleteModalOpen(false);
- useEffect(() => {
- /** API 준비 전 더미 데이터 사용*/
- setChatList(mockup);
- }, []);
-
return {
isEditing,
activeFilter,
setActiveFilter,
- chatList,
selectChatList,
handleToggleEdit,
handleCheckChange,
diff --git a/src/pages/chat-list/types/chat-list-type.ts b/src/pages/chat-list/types/chat-list-type.ts
deleted file mode 100644
index 7afd2db2..00000000
--- a/src/pages/chat-list/types/chat-list-type.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export interface Chat {
- clientId: number;
- clientName: string;
- tagTitle: string;
- lastChat: string;
- lastChatTime: string;
- unreadCount: number;
-};
\ No newline at end of file
diff --git a/src/shared/components/chat/chat-list-item/ChatListItem.stories.tsx b/src/shared/components/chat/chat-list-item/ChatListItem.stories.tsx
index 18afb099..eb9e8fdc 100644
--- a/src/shared/components/chat/chat-list-item/ChatListItem.stories.tsx
+++ b/src/shared/components/chat/chat-list-item/ChatListItem.stories.tsx
@@ -10,7 +10,7 @@ const meta: Meta = {
},
tags: ['autodocs'],
argTypes: {
- profileImage: {
+ profileImageUrl: {
control: 'text',
description: '프로필 이미지 URL',
},
@@ -19,19 +19,19 @@ const meta: Meta = {
description:
'편집 모드 활성화 여부. true인 경우에 컴포넌트 전체에 클릭 이벤트 발생',
},
- clientName: {
+ name: {
control: 'text',
description: '고객 이름',
},
- tagTitle: {
+ foodTruckName: {
control: 'text',
description: '고객에게 붙은 태그',
},
- lastChat: {
+ lastMessage: {
control: 'text',
description: '마지막으로 수신된 채팅 메시지',
},
- lastChatTime: {
+ lastMessageSendTime: {
control: 'text',
description: '마지막 채팅 수신 시간',
},
@@ -54,10 +54,10 @@ export default meta;
type Story = StoryObj;
const defaultArgs = {
- profileImage: 'https://via.placeholder.com/52',
- clientName: '고객이름',
- tagTitle: '고고 푸드트럭',
- lastChatTime: '오후 3:40',
+ profileImageUrl: 'https://via.placeholder.com/52',
+ name: '고객이름',
+ foodTruckName: '고고 푸드트럭',
+ lastMessageSendTime: '오후 3:40',
isEditing: false,
isChecked: false,
};
@@ -65,7 +65,7 @@ const defaultArgs = {
export const Default: Story = {
args: {
...defaultArgs,
- lastChat: '네, 확인했습니다. 내일 연락드리겠습니다.',
+ lastMessage: '네, 확인했습니다. 내일 연락드리겠습니다.',
unreadCount: 3,
},
};
@@ -73,7 +73,7 @@ export const Default: Story = {
export const Read: Story = {
args: {
...defaultArgs,
- lastChat: '감사합니다! 좋은 하루 되세요.',
+ lastMessage: '감사합니다! 좋은 하루 되세요.',
unreadCount: 0,
},
};
@@ -81,8 +81,8 @@ export const Read: Story = {
export const LongText: Story = {
args: {
...defaultArgs,
- clientName: '건국대학교 총학생회 축제준비위원회 부팀장 고객님',
- lastChat:
+ name: '건국대학교 총학생회 축제준비위원회 부팀장 고객님',
+ lastMessage:
'안녕하세요, 문의주신 내용에 대한 답변입니다. 저희 학교의 축제를 맞이하여 총 7대의 푸드트럭을 각 건물 앞에 요청드리려고 합니다.',
unreadCount: 1,
},
@@ -91,8 +91,8 @@ export const LongText: Story = {
export const NoProfileImage: Story = {
args: {
...defaultArgs,
- profileImage: '',
- lastChat: '프로필 이미지가 없는 사용자입니다.',
+ profileImageUrl: '',
+ lastMessage: '프로필 이미지가 없는 사용자입니다.',
unreadCount: 0,
},
};
diff --git a/src/shared/components/chat/chat-list-item/ChatListItem.tsx b/src/shared/components/chat/chat-list-item/ChatListItem.tsx
index 43ee5fbe..e06e6ac9 100644
--- a/src/shared/components/chat/chat-list-item/ChatListItem.tsx
+++ b/src/shared/components/chat/chat-list-item/ChatListItem.tsx
@@ -3,24 +3,24 @@ import Tag from '@ui/tag/Tag';
import { cn } from '@utils/cn';
interface ChatListItemProps {
- profileImage?: string;
+ profileImageUrl?: string;
isEditing: boolean;
- clientName: string;
- tagTitle: string;
- lastChat: string;
- lastChatTime: string;
+ name: string;
+ foodTruckName: string;
+ lastMessage: string;
+ lastMessageSendTime: string;
unreadCount: number;
isChecked: boolean;
handleCheckChange: (_checked: boolean) => void;
}
export default function ChatListItem({
- profileImage,
+ profileImageUrl,
isEditing,
- clientName,
- tagTitle,
- lastChat,
- lastChatTime,
+ name,
+ foodTruckName,
+ lastMessage,
+ lastMessageSendTime,
unreadCount,
isChecked,
handleCheckChange,
@@ -51,10 +51,10 @@ export default function ChatListItem({
)}
- {profileImage ? (
+ {profileImageUrl ? (

) : (
@@ -66,20 +66,20 @@ export default function ChatListItem({
- {clientName}
+ {name}
-
+
0 ? 'text-grayscale-900' : 'text-grayscale-500'}`}
>
- {lastChat}
+ {lastMessage}
- {lastChatTime}
+ {lastMessageSendTime}
{unreadCount > 0 && (