Skip to content

Commit

Permalink
Merge pull request #277 from SWM-FIRE/FIRE-774-dm-프론트-개발
Browse files Browse the repository at this point in the history
FIRE-774 add direct message frame
  • Loading branch information
071yoon authored Oct 24, 2022
2 parents 994ee57 + d8467dc commit d8c0b09
Show file tree
Hide file tree
Showing 10 changed files with 268 additions and 2 deletions.
118 changes: 118 additions & 0 deletions src/components/atoms/chattingModal/ChattingModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import styled from 'styled-components';
import chattingModalStore from 'src/stores/chattingModalStore';
import useUser from 'src/hooks/useUser';
import MyAvatar from 'src/assets/avatar/MyAvatar';
import ChattingPortal from './ChattingPortal';
import SendChat from './SendChat';
import { ReactComponent as Close } from '../../../assets/svg/X.svg';

export default function ChattingModal() {
const { closeChattingModal, chattingFriend } = chattingModalStore();
const { isLoading, error, data } = useUser(Number(chattingFriend));
if (isLoading)
return (
<ChattingPortal>
<Outside onClick={closeChattingModal}>
<Container onClick={(e) => e.stopPropagation()}>
<Header />
<Content>{chattingFriend}</Content>
<Footer>메세지창</Footer>
</Container>
</Outside>
</ChattingPortal>
);
if (error)
return (
<ChattingPortal>
<Outside onClick={closeChattingModal}>
<Container onClick={(e) => e.stopPropagation()}>
<Header />
<Content>{chattingFriend}</Content>
<Footer>메세지창</Footer>
</Container>
</Outside>
</ChattingPortal>
);

return (
<ChattingPortal>
<Outside onClick={closeChattingModal}>
<Container onClick={(e) => e.stopPropagation()}>
<CloseContainer onClick={closeChattingModal}>
<Close />
</CloseContainer>
<Header>
<Avatar>
<MyAvatar num={data?.avatar} />
{data?.nickname}
</Avatar>
</Header>
<Content>{chattingFriend}</Content>
<Footer>
<SendChat uid={data?.uid} />
</Footer>
</Container>
</Outside>
</ChattingPortal>
);
}

const CloseContainer = styled.div`
position: absolute;
top: 2rem;
right: 2rem;
cursor: pointer;
`;

const Avatar = styled.div`
display: flex;
height: 5rem;
font-size: 1.6rem;
align-items: center;
svg {
height: 100%;
}
`;

const Outside = styled.div`
position: fixed;
width: 100vw;
height: 100vh;
z-index: 999;
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(0, 0, 0, 0.5);
`;

const Header = styled.div`
width: 100%;
height: 8rem;
color: white;
border-bottom: 1px solid #374151;
display: flex;
align-items: center;
`;

const Content = styled.div`
width: 100%;
flex-grow: 1;
`;

const Footer = styled.div`
width: 100%;
`;

const Container = styled.div`
width: 30%;
min-width: 40rem;
height: 80%;
min-height: 30rem;
position: relative;
display: flex;
justify-content: space-between;
flex-direction: column;
background-color: #23262f;
padding: 2rem;
border-radius: 1rem;
`;
8 changes: 8 additions & 0 deletions src/components/atoms/chattingModal/ChattingPortal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import ReactDOM from 'react-dom';

const ChattingPortal = ({ children }) => {
const el = document.getElementById('chatting-modal');
return ReactDOM.createPortal(children, el);
};

export default ChattingPortal;
96 changes: 96 additions & 0 deletions src/components/atoms/chattingModal/SendChat.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import React, { useState, useRef } from 'react';
import styled from 'styled-components';
import { ReactComponent as MessageSend } from '../../../assets/svg/MessageSend.svg';

export default function SendChat({ uid }: { uid: number }) {
const [newMessage, setNewMessage] = useState('');
const inputRef = useRef(null);

const onMessageChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
event.preventDefault();
setNewMessage(() => event.target.value);
autoGrow();
};

const autoGrow = () => {
if (inputRef.current) {
inputRef.current.style.height = '2rem';
inputRef.current.style.height = inputRef.current.scrollHeight
.toString()
.concat('px');
console.log(inputRef.current.style.height);
}
};

const onSubmit = (event: React.MouseEvent<HTMLButtonElement>) => {
event.preventDefault();
if (newMessage.trim() === '') return;
console.log('send to', uid, newMessage);
// emit
setNewMessage(() => '');
if (inputRef.current) {
inputRef.current.style.height = '2rem';
}
};

const onKeyPress = (event) => {
if (event.key === 'Enter') {
if (!event.shiftKey) {
event.preventDefault();
onSubmit(event);
}
}
};

return (
<SubmitMessage>
<Input
placeholder="Write your message...."
value={newMessage}
ref={inputRef}
rows={1}
onChange={onMessageChange}
onKeyPress={onKeyPress}
/>
<Button onClick={onSubmit}>
<MessageSend />
</Button>
</SubmitMessage>
);
}

const SubmitMessage = styled.form`
width: 100%;
max-height: 19rem;
border-radius: 1rem;
padding: 1.5rem 2rem;
background-color: #313540;
z-index: 999;
`;

const Input = styled.textarea`
width: calc(100% - 2.7rem);
font-size: 1.3rem;
background-color: #313540;
font-family: IBMPlexSansKRRegular;
color: rgba(255, 255, 255, 1);
min-height: 2rem;
max-height: 13rem;
resize: none;
::-webkit-scrollbar {
width: 0.3rem;
}
&:focus {
outline: none;
}
`;

const Button = styled.button`
cursor: pointer;
float: right;
svg {
width: 2rem;
height: 2rem;
}
`;
11 changes: 11 additions & 0 deletions src/components/atoms/chattingModal/chattingUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import chattingModalStore from 'src/stores/chattingModalStore';

export default function ChattingUtil() {
const { openChattingModal, setChattingFriend } = chattingModalStore();
const openChat = (friendUid: number) => {
setChattingFriend(friendUid);
openChattingModal();
};

return { openChat };
}
4 changes: 4 additions & 0 deletions src/components/layout/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ import { ReactChannelIO } from 'react-channel-plugin';
import { Outlet } from 'react-router-dom';
import { Toaster } from 'react-hot-toast';
import mainModalStore from 'src/stores/mainModalStore';
import chattingModalStore from 'src/stores/chattingModalStore';
import Header from './Header';
import Footer from './Footer';
import userStore from '../../stores/userStore';
import NoticeModal from '../notice/NoticeModal';
import ChattingModal from '../atoms/chattingModal/ChattingModal';

export default function MainLayout() {
const { uid, nickname } = userStore();
Expand All @@ -17,6 +19,7 @@ export default function MainLayout() {
name: nickname,
}
: null;
const { isChattingModal } = chattingModalStore();
return (
<>
{uid ? (
Expand All @@ -39,6 +42,7 @@ export default function MainLayout() {
/>
)}
{isOpenNoticeModal && <NoticeModal />}
{isChattingModal && <ChattingModal />}
<Toaster />
<Header />
<Outlet />
Expand Down
4 changes: 4 additions & 0 deletions src/components/layout/RoomLayout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import React from 'react';
import { ReactChannelIO } from 'react-channel-plugin';
import { Outlet } from 'react-router-dom';
import chattingModalStore from 'src/stores/chattingModalStore';
import ChattingModal from '../atoms/chattingModal/ChattingModal';
import userStore from '../../stores/userStore';

export default function RoomLayout() {
const { uid, nickname } = userStore();
const { isChattingModal } = chattingModalStore();
const profile = uid
? {
email: localStorage.getItem('email'),
Expand All @@ -13,6 +16,7 @@ export default function RoomLayout() {
: null;
return (
<>
{isChattingModal && <ChattingModal />}
<Outlet />
{uid ? (
<ReactChannelIO
Expand Down
5 changes: 4 additions & 1 deletion src/components/profile/friends/FriendList.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
/* eslint-disable no-unused-vars */
import styled from 'styled-components';
import media from 'src/styles/media';
import { detailedFriend } from 'src/interface/singleFriend.interface';
import ChattingUtil from 'src/components/atoms/chattingModal/chattingUtil';
import { ReactComponent as SendImage } from '../../../assets/svg/MessageSend.svg';
import FriendIcon from './FriendIcon';

Expand All @@ -9,6 +11,7 @@ export default function FriendList({
}: {
friendList: detailedFriend[];
}) {
const { openChat } = ChattingUtil();
const filteredFriends = friendList.map((friend) =>
friend.role === 'RECEIVER' ? friend.sender : friend.receiver,
);
Expand All @@ -18,7 +21,7 @@ export default function FriendList({
{filteredFriends.map((friend) => (
<Component key={friend?.uid}>
<FriendIcon friend={friend} />
<SendMessage>
<SendMessage onClick={() => openChat(friend?.uid)}>
<SendButton>
<SendImage />
</SendButton>
Expand Down
4 changes: 3 additions & 1 deletion src/components/profile/userProfile/UserProfile.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import useSingleFriend from 'src/hooks/friend/useSingleFriend';
import useRequestFriend from 'src/hooks/friend/useRequestFriend';
import useDeleteFriendRequest from 'src/hooks/friend/useDeleteFriendRequest';
import userStore from 'src/stores/userStore';
import ChattingUtil from 'src/components/atoms/chattingModal/chattingUtil';
import Avatar from '../../atoms/Avatar';
import Group from './Group';
import Badge from './Badge';
Expand All @@ -26,6 +27,7 @@ export default function UserProfile({ isMe, setIsEdit, userId, isModal }) {
const { setClear } = userStore();
const navigate = useNavigate();
const { isLoading, error, refetch, data } = useUser(Number(userId));
const { openChat } = ChattingUtil();

const {
isLoading: friendLoading,
Expand Down Expand Up @@ -159,7 +161,7 @@ export default function UserProfile({ isMe, setIsEdit, userId, isModal }) {
)}
{isFriend ? (
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
<Button isModal={isModal}>
<Button isModal={isModal} onClick={() => openChat(data.uid)}>
<SendMessageBlack />
채팅하기
</Button>
Expand Down
1 change: 1 addition & 0 deletions src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ root.render(
// <StrictMode>
<>
<GlobalStyle />
<div id="chatting-modal" />
<div id="modal" />
<App />
</>,
Expand Down
19 changes: 19 additions & 0 deletions src/stores/chattingModalStore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import create from 'zustand';

interface Modal {
chattingFriend: number;
setChattingFriend: (_by: number) => void;
isChattingModal: boolean;
closeChattingModal: () => void;
openChattingModal: () => void;
}

const chattingModalStore = create<Modal>((set) => ({
chattingFriend: -1,
setChattingFriend: (by) => set(() => ({ chattingFriend: by })),
isChattingModal: false,
closeChattingModal: () => set(() => ({ isChattingModal: false })),
openChattingModal: () => set(() => ({ isChattingModal: true })),
}));

export default chattingModalStore;

0 comments on commit d8c0b09

Please sign in to comment.