Skip to content

Commit

Permalink
Merge pull request #156 from TheUpperPart/Feat/#149
Browse files Browse the repository at this point in the history
Feat/#149: 채팅기능 추가
  • Loading branch information
pp449 authored Oct 8, 2023
2 parents e026b4c + ef2e181 commit a011919
Show file tree
Hide file tree
Showing 9 changed files with 529 additions and 163 deletions.
120 changes: 68 additions & 52 deletions __mocks__/handlers/boardHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ interface ChannelInfo {
}

interface BoardsInfo {
[key: string]: Channels[];
[key: string]: {
myMatchRound: number;
myMatchId: number;
channelBoardLoadDtdList: Channels[];
};
}

const mockChannelInfo: ChannelInfo = {
Expand Down Expand Up @@ -38,57 +42,69 @@ const mockChannelInfo: ChannelInfo = {
};

const boardsInfo: BoardsInfo = {
'123': [
{
boardId: 'aaa',
boardTitle: '공지사항',
boardIndex: 0,
},
{
boardId: 'bbb',
boardTitle: '게임 룰',
boardIndex: 1,
},
{
boardId: 'ccc',
boardTitle: '커뮤니티',
boardIndex: 2,
},
],
'234': [
{
boardId: 'bbb',
boardTitle: '리그 공지사항',
boardIndex: 0,
},
{
boardId: 'ccc',
boardTitle: '참여자 규칙',
boardIndex: 1,
},
{
boardId: 'ddd',
boardTitle: '참여하기',
boardIndex: 2,
},
],
'456': [
{
boardId: 'eee',
boardTitle: '리그 공지사항',
boardIndex: 0,
},
{
boardId: 'fff',
boardTitle: '참여자 규칙',
boardIndex: 1,
},
{
boardId: 'ggg',
boardTitle: '참여하기',
boardIndex: 2,
},
],
'123': {
myMatchRound: 0,
myMatchId: 0,
channelBoardLoadDtdList: [
{
boardId: 'aaa',
boardTitle: '공지사항',
boardIndex: 0,
},
{
boardId: 'bbb',
boardTitle: '게임 룰',
boardIndex: 1,
},
{
boardId: 'ccc',
boardTitle: '커뮤니티',
boardIndex: 2,
},
],
},
'234': {
myMatchRound: 1,
myMatchId: 1,
channelBoardLoadDtdList: [
{
boardId: 'bbb',
boardTitle: '리그 공지사항',
boardIndex: 0,
},
{
boardId: 'ccc',
boardTitle: '참여자 규칙',
boardIndex: 1,
},
{
boardId: 'ddd',
boardTitle: '참여하기',
boardIndex: 2,
},
],
},
'456': {
myMatchRound: 2,
myMatchId: 2,
channelBoardLoadDtdList: [
{
boardId: 'eee',
boardTitle: '리그 공지사항',
boardIndex: 0,
},
{
boardId: 'fff',
boardTitle: '참여자 규칙',
boardIndex: 1,
},
{
boardId: 'ggg',
boardTitle: '참여하기',
boardIndex: 2,
},
],
},
};

const boardHandlers = [
Expand Down
172 changes: 129 additions & 43 deletions __mocks__/handlers/matchHandlers.ts

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
"prettier": "^2.8.8",
"typescript": "4.9.5"
},
"resolutions": {
"@types/react": "17.0.2",
"@types/react-dom": "17.0.2"
},
"msw": {
"workerDirectory": "public"
}
Expand Down
157 changes: 151 additions & 6 deletions src/components/RoundCheckIn/CallAdminChat.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,133 @@
import { MatchMessages, MatchPlayerScoreInfos } from '@components/RoundCheckIn';
import { css } from '@emotion/react';
import styled from '@emotion/styled';
import Image from 'next/image';
import { Client } from '@stomp/stompjs';
import React, { useEffect, useState, ChangeEvent } from 'react';
import { useRouter } from 'next/router';

interface CallAdminChatProps {
client: Client | undefined;
matchId: string;
players: MatchPlayerScoreInfos[];
matchMessage: MatchMessages[];
requestUser: number;
}

const CallAdminChat = ({
client,
matchId,
players,
matchMessage,
requestUser,
}: CallAdminChatProps) => {
const [chats, setChats] = useState<MatchMessages[]>([]);
const [inputMessage, setInputMessage] = useState('');
const router = useRouter();
const { channelLink } = router.query;

const handleInputMessage = (e: ChangeEvent<HTMLInputElement>) => {
setInputMessage(e.target.value);
};

const handleKeyPress = (event: React.KeyboardEvent<HTMLInputElement>) => {
if (event.key === 'Enter') {
event.preventDefault();
sendMessage();
}
};

const sendMessage = () => {
if (!client || inputMessage.length === 0) return;
const requestUserParticipantId = players.find(
(player) => player.matchPlayerId === requestUser,
)?.participantId;

const newMessage = {
channelId: channelLink,
content: inputMessage,
matchId,
participantId: requestUserParticipantId,
type: 'TEXT',
};
client.publish({
destination: `/app/match/chat`,
body: JSON.stringify(newMessage),
});
setInputMessage('');
};

const findUserIMG = (playerParticipantId: number): string => {
const user = players.find((player) => player.participantId === playerParticipantId);

if (!user) return '';
return user.profileSrc;
};

const findUserName = (playerParticipantId: number): string => {
const user = players.find((player) => player.participantId === playerParticipantId);
if (!user) return '';
return user.gameId;
};

useEffect(() => {
if (!client) return;
const subscription = client.subscribe(`/match/${matchId}/chat`, (data) => {
setChats((prevChat) => [...prevChat, JSON.parse(data.body)]);
});

return () => {
subscription.unsubscribe();
};
}, [client]);

useEffect(() => {
if (!matchMessage || matchMessage.length === 0) return;
setChats(matchMessage);
}, [matchMessage]);

const CallAdminChat = () => {
return (
<Container>
<Header>
<div>Chat</div>
<CallAdminButton>Call Admin</CallAdminButton>
</Header>
<ChattingWrapper></ChattingWrapper>
<ChattingWrapper>
{chats.length !== 0 &&
chats.map((message, idx) => (
<ChattingInfo key={idx}>
<ChattingContent>
<ImageWrapper>
<Image
src={findUserIMG(message.participantId)}
alt='프로필사진'
width={45}
height={45}
/>
</ImageWrapper>
<ContentWrapper>
<ContentName>{findUserName(message.participantId)}</ContentName>
<ContentText>{message.content}</ContentText>
</ContentWrapper>
</ChattingContent>
</ChattingInfo>
))}
</ChattingWrapper>
<div
css={css`
position: relative;
`}
>
<InputChat />
<SubmitButton>입력</SubmitButton>
<InputChat
type='text'
placeholder='메세지를 입력해주세요'
value={inputMessage}
onChange={handleInputMessage}
onKeyUp={handleKeyPress}
/>
<SubmitButton onClick={sendMessage} disabled={inputMessage.length === 0}>
입력
</SubmitButton>
</div>
</Container>
);
Expand All @@ -24,7 +136,7 @@ const CallAdminChat = () => {
export default CallAdminChat;

const Container = styled.div`
height: 40rem;
height: 50rem;
background: #fff;
border-radius: 0.5rem;
`;
Expand All @@ -47,7 +159,40 @@ const CallAdminButton = styled.button`
`;

const ChattingWrapper = styled.div`
height: 30rem;
height: 40rem;
overflow: scroll;
`;

const ImageWrapper = styled.div`
border-radius: 0.3rem;
`;

const ContentWrapper = styled.div`
margin-left: 0.5rem;
`;

const ContentName = styled.div`
padding-top: 0.2rem;
`;

const ContentText = styled.div`
padding: 0.5rem;
border: 1px solid black;
border-radius: 0 1rem 1rem 1rem;
display: flex;
align-items: center;
font-size: 1.3rem;
`;

const ChattingInfo = styled.div`
min-height: 5rem;
display: flex;
align-items: center;
margin: 0.4rem;
`;

const ChattingContent = styled.div`
display: flex;
`;

const InputChat = styled.input`
Expand Down
24 changes: 22 additions & 2 deletions src/components/RoundCheckIn/CheckInPage.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import Icon from '@components/Icon';
import { MatchMessages, MatchPlayerScoreInfos } from '@components/RoundCheckIn';
import CallAdminChat from '@components/RoundCheckIn/CallAdminChat';
import styled from '@emotion/styled';
import { Client } from '@stomp/stompjs';

interface CheckInPageProps {
ParticipantCheckin: () => void;
client: Client | undefined;
matchId: string;
players: MatchPlayerScoreInfos[];
matchMessage: MatchMessages[];
requestUser: number;
}

const CheckInPage = ({ ParticipantCheckin }: CheckInPageProps) => {
const CheckInPage = ({
ParticipantCheckin,
client,
matchId,
players,
matchMessage,
requestUser,
}: CheckInPageProps) => {
return (
<Container>
<RemainTimeWrapper>
Expand All @@ -19,7 +33,13 @@ const CheckInPage = ({ ParticipantCheckin }: CheckInPageProps) => {
<Button>기권</Button>
</ButtonWrapper>
<ChattingWrapper>
<CallAdminChat />
<CallAdminChat
client={client}
matchId={matchId}
players={players}
matchMessage={matchMessage}
requestUser={requestUser}
/>
</ChattingWrapper>
</Container>
);
Expand Down
Loading

0 comments on commit a011919

Please sign in to comment.