Skip to content

Commit

Permalink
[merge] 채팅 버그 수정
Browse files Browse the repository at this point in the history
채팅 배포, react-query, 모바일 UI 버그 수정
  • Loading branch information
Im-younique authored Dec 19, 2023
2 parents ee5d643 + e8ed8cd commit 2a2b000
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 116 deletions.
6 changes: 0 additions & 6 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@
"storybook": "storybook dev -p 6006",
"build-storybook": "storybook build"
},
"proxy": {
"/ws-connection": {
"target": "wss://www.reduck.site",
"ws": true
}
},
"dependencies": {
"@iconify/react": "^4.1.0",
"@reduxjs/toolkit": "^1.9.5",
Expand Down
16 changes: 10 additions & 6 deletions client/src/components/Chat/chat-message.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,18 @@ export default function ChatMessage({
}: IChatMessage) {
const Style = {
my: {
wrapper: 'ml-auto mr2 flex-row-reverse',
wrapper: 'ml-auto mr-2 flex-row-reverse',
box: 'text-right',
messageWrapper: 'flex-row-reverse',
message: 'bg-indigo-500 rounded-tr-none ml-auto',
message:
'bg-indigo-500 ml-auto after:right-0 after:border-l-indigo-500 after:border-r-0 after:-mr-2',
},
other: {
wrapper: 'mr-auto ml-2',
wrapper: 'mr-auto ml-2 after:left-0',
box: 'text-left',
messageWrapper: 'flex-row',
message: 'bg-slate-500 rounded-tl-none',
message:
'bg-slate-500 after:left-0 after:border-r-slate-500 after:border-l-0 after:-ml-2',
},
};
const time = formatDateToHHMM(messageTime);
Expand All @@ -53,9 +55,11 @@ export default function ChatMessage({
)}
<div className={Style[type].box}>
<span>{name}</span>
<div className={`flex items-end gap-2 ${Style[type].messageWrapper}`}>
<div
className={`relative flex items-end gap-2 ${Style[type].messageWrapper}`}
>
<div
className={`w-fit p-2 text-white text-left rounded-xl ${Style[type].message}`}
className={`w-fit p-2 text-white text-left rounded-xl ${Style[type].message} after:content-[""] after:absolute after:top-[40%] after:w-0 after:h-0 after:border-8 after:border-solid after:border-transparent after:border-t-0 after:-mt-1`}
>
<span>{message}</span>
</div>
Expand Down
134 changes: 78 additions & 56 deletions client/src/components/Chat/chat-room.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
// react, next
import React, { useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';

// react-query
import { useInfiniteQuery } from '@tanstack/react-query';

// components
import ChatMessage from '@/components/Chat/chat-message';
import DateDivider from '@/components/Chat/date-divider';
import { Icon } from '@iconify/react';

// types
import { IChatMessage } from '@/types';
import { IChatMessage, IChatRoomInfo } from '@/types';
import { IReduxState } from '@/types/redux/IReduxState';

// utils
import { parseDate } from '@/util';
Expand All @@ -24,20 +27,24 @@ import {
} from '@/constants/constant';

interface IChatRoom {
roomId: string;
roomInfo: IChatRoomInfo;
chatList: IChatMessage[];
currentUid: string;
setChatList: React.Dispatch<React.SetStateAction<IChatMessage[]>>;
handleSendMessage: (chatMessage: string) => void;
handleDisconnect: () => void;
}

export default function ChatRoom({
roomId,
roomInfo,
chatList,
currentUid,
setChatList,
handleSendMessage,
handleDisconnect,
}: IChatRoom) {
const user = useSelector((state: IReduxState) => state.auth);

const { roomId, roomName } = roomInfo;

const [chatMessage, setChatMessage] = useState('');
const [isScrolling, setIsScrolling] = useState(false);

Expand All @@ -62,9 +69,9 @@ export default function ChatRoom({
};

const { data, fetchNextPage, hasNextPage, isFetching } = useInfiniteQuery({
queryKey: ['chat'],
queryKey: ['chat', roomId],
queryFn: ({ pageParam }) => getRoomChat({ roomId, messageId: pageParam }),
getNextPageParam: (lastPage) => lastPage?.nextPageParam,
getNextPageParam: (lastPage) => lastPage.nextPageParam,
});

useEffect(() => {
Expand Down Expand Up @@ -122,56 +129,71 @@ export default function ChatRoom({
}, [isFetching, hasNextPage]);

return (
<div className="relative flex flex-col flex-1 ml-4 border border-black">
<div className="flex flex-col h-full overflow-y-scroll" ref={chatRoomRef}>
{chatList?.map((val, idx) => {
const {
messageId,
message,
userId: senderId,
name,
userProfileImgPath,
messageTime,
} = val;

return (
<React.Fragment key={messageId}>
{idx === 0 ||
(idx !== 0 &&
parseDate(chatList[idx - 1].messageTime) !==
parseDate(messageTime) && (
<DateDivider
messageTime={parseDate(messageTime) as string}
/>
))}
<ChatMessage
type={senderId === currentUid ? 'my' : 'other'}
message={message}
name={name}
userProfileImgPath={userProfileImgPath}
messageTime={messageTime}
/>
</React.Fragment>
);
})}
</div>
<div className="flex p-2.5 sticky bottom-0 bg-white">
<input
type="text"
className="relative flex-1 p-1 border border-black"
value={chatMessage}
ref={messageRef}
onChange={handleMessageChange}
onKeyDown={handleKeyDown}
/>
<button
type="button"
disabled={chatMessage.length === 0}
onClick={handleClickSend}
className="w-20 p-2 ml-2 text-sm font-semibold text-white bg-indigo-600 rounded-md hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:opacity-70 sm:w-24 sm:text-base"
<div className="absolute z-10 bg-white h-full w-full sm:relative">
<div className="relative flex flex-col h-full flex-1 border border-black sm:ml-4">
<div className="p-2 text-center shadow-md mb-1">
<Icon
icon="eva:arrow-ios-back-outline"
fontSize={28}
color="black"
className="absolute left-0 top-1.5 hover:cursor-pointer"
onClick={handleDisconnect}
/>
<p>{roomName}</p>
</div>
<div
className="flex flex-col h-full overflow-y-scroll"
ref={chatRoomRef}
>
전송
</button>
{chatList?.map((val, idx) => {
const {
messageId,
message,
userId: senderId,
name,
userProfileImgPath,
messageTime,
} = val;

return (
<React.Fragment key={messageId}>
{idx === 0 ||
(idx !== 0 &&
parseDate(chatList[idx - 1].messageTime) !==
parseDate(messageTime) && (
<DateDivider
messageTime={parseDate(messageTime) as string}
/>
))}
<ChatMessage
type={senderId === user.userId ? 'my' : 'other'}
message={message}
name={name}
userProfileImgPath={userProfileImgPath}
messageTime={messageTime}
/>
</React.Fragment>
);
})}
</div>
<div className="flex p-2.5 sticky bottom-0 bg-white">
<input
type="text"
className="relative flex-1 p-1 border border-black"
value={chatMessage}
ref={messageRef}
onChange={handleMessageChange}
onKeyDown={handleKeyDown}
/>
<button
type="button"
disabled={chatMessage.length === 0}
onClick={handleClickSend}
className="w-20 p-2 ml-2 text-sm font-semibold text-white bg-indigo-600 rounded-md hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 disabled:opacity-70 sm:w-24 sm:text-base"
>
전송
</button>
</div>
</div>
</div>
);
Expand Down
16 changes: 9 additions & 7 deletions client/src/components/Chat/chat-user-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import { getRecommandUser, getUserChatRoom } from '@/service/chat-get';
import UserTile from './user-tile';

// types
import { IUserInfo, IChatUserDto } from '@/types';
import { IUserInfo, IChatUserDto, IChatRoomInfo } from '@/types';
import { IReduxState } from '@/types/redux/IReduxState';

interface IChatUserList {
enteredRoomId: string;
handleConnect: (roomId: string) => void;
handleConnect: (roomInfo: IChatRoomInfo) => void;
handleDisconnect: () => void;
}
export default function ChatUserList({
Expand Down Expand Up @@ -44,9 +44,9 @@ export default function ChatUserList({
setRecommandUser(recommandData);
}, [userId]);

const handleEnterRoom = (roomId: string) => {
const handleEnterRoom = (roomInfo: IChatRoomInfo) => {
handleDisconnect();
handleConnect(roomId);
handleConnect(roomInfo);
loadUserChatList();
};

Expand All @@ -55,9 +55,11 @@ export default function ChatUserList({
}, [user]);

return (
<section className="relative border border-black w-[30%] text-center">
<section className="flex flex-col my-2.5 overflow-y-scroll">
<span>채팅방 목록</span>
<section className="relative border border-black w-full sm:w-[30%] text-center">
<div className="p-2 text-center shadow-md">
<p>채팅방 목록</p>
</div>
<section className="flex flex-col mb-2.5 overflow-y-scroll">
{chatUserList?.map((dto) => {
const {
lastChatMessage,
Expand Down
53 changes: 31 additions & 22 deletions client/src/components/Chat/user-tile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ import { BASE_URL } from '@/service/base/api';
// utils
import { formatDateToString } from '@/util';

// types
import { IChatRoomInfo } from '@/types';

// constant
import { ModalType, errorMessage } from '@/constants/constant';

Expand All @@ -23,9 +26,9 @@ interface IUserTile {
enteredRoomId: string;
src?: string;
userId: string;
name?: string;
name: string;
description: string;
handleEnterRoom: (roomId: string) => void;
handleEnterRoom: (roomInfo: IChatRoomInfo) => void;
type: 'recommand' | 'room';
lastChatMessageTime?: string;
unReadMessageCount?: number;
Expand All @@ -44,24 +47,27 @@ const UserTile = ({
unReadMessageCount,
}: IUserTile) => {
const { openModal } = useModal();
const handleRoomCheck = async () => {

const handleClick = async () => {
if (type === 'room') {
handleEnterRoom(roomId as string);
} else {
const otherIds = [userId];
try {
const data = await createChatRoom({
otherIds,
roomName: '',
});
const { roomId } = data;
handleEnterRoom(roomId);
} catch {
openModal({
type: ModalType.ERROR,
message: errorMessage.failedCreateChatRoom,
});
}
handleEnterRoom({ roomId: roomId as string, roomName: name });
}
};

const handleRecommandChatStart = async () => {
const otherIds = [userId];
try {
const data = await createChatRoom({
otherIds,
roomName: name,
});
const { roomId, roomName } = data;
handleEnterRoom({ roomId, roomName });
} catch {
openModal({
type: ModalType.ERROR,
message: errorMessage.failedCreateChatRoom,
});
}
};

Expand All @@ -72,7 +78,7 @@ const UserTile = ({
return (
<div
className={`flex gap-2 font-semibold items-center px-2 py-4 ${addedStyle}`}
onDoubleClick={handleRoomCheck}
onClick={handleClick}
>
<Avatar src={src ? `${BASE_URL}${src}` : ''} alt="user_icon" size="sm" />
<div className="flex flex-col flex-1 overflow-hidden text-left">
Expand All @@ -81,9 +87,12 @@ const UserTile = ({
{description}
</span>
</div>
<div className="inline-block w-8 h-8 disabled:opacity-70 sm:w-14 sm:h-10">
<div className="inline-block w-14 h-10 disabled:opacity-70">
{type === 'recommand' ? (
<button className="w-8 text-right sm:w-14" onClick={handleRoomCheck}>
<button
className="w-8 text-right sm:w-14"
onClick={handleRecommandChatStart}
>
<Icon icon="lucide:message-circle" fontSize={28} color="black" />
</button>
) : (
Expand Down
5 changes: 3 additions & 2 deletions client/src/components/common/UserInfo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,14 @@ export default function UserInfo({ userData }: { userData: IUserInfo }) {
try {
const data = await createChatRoom({
otherIds: [userId],
roomName: '',
roomName: name,
});
const { roomId } = data;
const { roomId, roomName } = data;
router.push({
pathname: '/chat',
query: {
roomId,
roomName,
},
});
} catch (error) {
Expand Down
Loading

0 comments on commit 2a2b000

Please sign in to comment.