Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIRE-774 add direct message frame #277

Merged
merged 1 commit into from
Oct 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;