Skip to content
Open
6 changes: 6 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"trailingComma": "es5",
"tabWidth": 2,
"semi": true,
"singleQuote": true
}
20,212 changes: 20,196 additions & 16 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 4 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@
"@testing-library/user-event": "^12.2.0",
"react": "^17.0.1",
"react-dom": "^17.0.1",
"react-scripts": "4.0.0",
"react-icons": "^4.2.0",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"react-scripts": "^4.0.0",
"styled-components": "^5.2.1",
"web-vitals": "^0.2.4"
},
Expand Down
Binary file added public/img/black.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/blue.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/green.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/navy.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/orange.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/purple.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/red.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/white.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/img/yellow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
109 changes: 106 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,113 @@
import React from 'react';
import { BrowserRouter, Link, Route, Switch} from 'react-router-dom';
import ChatListPage from './ChatListPage';
import FriendListPage from './FriendListPage';
import SettingPage from './SettingPage';
import styled, { createGlobalStyle } from 'styled-components';
import ChattingPage from './ChattingPage';
import { BsFillPersonFill, BsFillChatFill, BsThreeDots } from 'react-icons/bs';

const GlobalStyle = createGlobalStyle`
body {
display: flex;
align-items: center;
justify-content: center;
width: 100vw;
height: 100vh;
margin: 0;
background: orange;
}
`;

const AppLayout = styled.ul`
width: 70px;
list-style-type: none;
padding: 0;
margin: 0;
position: fixed;
height: 550px;
background-color: #F5F5F5;
float: left;
`;

const AppContainer = styled.div`
width: 350px;
height: 550px;
// border: solid;
// border-width: 1px;
Comment on lines +36 to +37
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

주석은 지워줍시당~!

display: flex;
flex-direction: column;
align-items: stretch;

box-shadow: 0 0 25px rgba(0, 0, 0, 0.25);
background: white;
overflow: auto;

`;

const StyledLink = styled(Link)`
text-decoration: none;
color: black;
`;
Comment on lines +48 to +51
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

styled-components 상속을 정말 잘 사용해주셨네요~ㅎㅎ


const StyledUl = styled.ul`
display: flex;
flex-direction: column;
list-style: none;
padding: 0;
align-items: center;
`;

const StyledLi = styled.li`
padding: 10px;
`;
export const initialList = [
{ id: 'black', name: '검은색', message: `I'm black`, img: '/img/black.png'},
{ id: 'red', name: '빨간색', message: `I'm Red`, img: '/img/red.png'},
{ id: 'orange', name: '주황색', message: `I'm Orange`, img: 'img/orange.png'},
{ id: 'yellow', name: '노란색', message: `I'm Yellow`, img:'img/yellow.png'},
{ id: 'green', name: '초록색', message: `I'm Green`, img: 'img/green.png'},
{ id: 'blue', name: '파란색', message: `I'm Blue`, img: 'img/blue.png'},
{ id: 'navy', name: '남색', message: `I'm Navy`, img: 'img/navy.png'},
{ id: 'purple', name: '보라색', message: `I'm Purple`, img: 'img/purple.png'},
]

function App() {

return (
<div > 12기 프론트엔드 개발팀장 투표 ^.^
</div>
<BrowserRouter>
<GlobalStyle/>
<AppContainer>
<AppLayout>
<StyledUl>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

StyledUl 보다는 좀 더 컴포넌트의 역할을 잘 드러낼 수 있는 네이밍이었으면 좋겠네용. Styled가 접두어로 붙은 모든 컴포넌트들도 마찬가지로요 ㅎㅎ

<StyledLi>
<StyledLink to="/">
<BsFillPersonFill size="30" />
</StyledLink>
</StyledLi>
<StyledLi>
<StyledLink to="/ChatListPage">
<BsFillChatFill size="25" />
</StyledLink>
</StyledLi>
<StyledLi>
<StyledLink to="/SettingPage">
<BsThreeDots size="30" />
</StyledLink>
</StyledLi>
</StyledUl>
Comment on lines +84 to +98
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depth가 너무 깊어져서 가독성이 많이 떨어집니다.
Component를 다른 파일로 분리하는건 어떨까요?

</AppLayout>
<div>
<Switch>
<Route exact path="/" component={FriendListPage} />
<Route path={`/ChattingPage/:id`} component={ChattingPage} />
<Route path="/ChatListPage" component={ChatListPage} />
<Route path="/SettingPage" component={SettingPage} />
</Switch>
</div>
Comment on lines +100 to +107
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

굳이 div를 넣을 이유가 있을까요?

</AppContainer>
</BrowserRouter>
);
}

export default App;
export default App;
69 changes: 69 additions & 0 deletions src/Chat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, { memo, useEffect, useRef } from 'react';
import styled from 'styled-components';

export const ChatContainer = styled.div`
display: flex;
flex-direction: column;
height: 415px;
overflow-y: scroll;
`
export const BlackChat = styled.div`
align-self: flex-start;
display: flex;
align-items: center;
padding: 5px;
div {
border: solid 1px #dcdcdc;
}
`
export const WhiteChat = styled.div`
align-self: flex-end;
display: flex;
align-items: center;
padding: 5px;
div {
background-color: #FFFA78;
border: ;
}
`
export const Text = styled.div`
padding: 5px;
margin: 5px;
border-radius: 15px;
`
export const ChatIcon = styled.img`
width: 30px;
height: 30px;
border-radius: 50%;
`

const Chat = memo(({ chatting, id }) => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

최적화를 잘 해주셨네요 ㅎㅎ

const scrollRef = useRef(null);

useEffect(() => {
scrollRef.current.scrollBy(0, scrollRef.current.scrollHeight);
}, [chatting]);

return(
<ChatContainer ref={scrollRef}>
{chatting.map((v,i) => {
return v.isMe ?
<WhiteChat key={i}>
<Text>
{v.text}
</Text>
<ChatIcon src="/img/white.png" alt="img" />
</WhiteChat>
:
<BlackChat key={i}>
<ChatIcon src={`/img/${id}.png`} alt="img" />
<Text>
{v.text}
</Text>
</BlackChat>
Comment on lines +51 to +63
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

같은 컴포넌트 구성이더라도
flex-direction 같은걸 이용해서 구현이 가능합니다.
말 주머니에 시간 정보를 추가하는등 여러 수정사항이 들어올 때마다
두 컴포넌트 모두 수정하기보단 css만 수정하는게 훨씬 편하겠죠?

})}
</ChatContainer>
);
});

export default Chat;
58 changes: 58 additions & 0 deletions src/ChatData.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
{
"black" : [
{"isMe": false, "text": "hey wassup You to party tonight?"},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
{"isMe": false, "text": "hey wassup You to party tonight?"},
{"userId": 0, "text": "hey wassup You to party tonight?"},

추후 단톡방 기능과 같이 확장성을 생각하면 userId를 이용해 본인 userID 와 비교해서 isMe 여부를 파악하는게 좋을 것 같아요.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 이 말에 동의합니다 ㅎㅎ

{"isMe": true, "text": "I wanna go, but nah"},
{"isMe": false, "text": "Why? I heard they prepared a lot. It must be cool"},
{"isMe": true, "text": "My professor just uploaded a new assignment, and the due is tomorrow"},
{"isMe": false, "text": "안녕하세요"}
],
"red" : [
{"isMe": false, "text": "hey wassup You to party tonight?"},
{"isMe": true, "text": "I wanna go, but nah"},
{"isMe": false, "text": "Why? I heard they prepared a lot. It must be cool"},
{"isMe": true, "text": "My professor just uploaded a new assignment, and the due is tomorrow"},
{"isMe": false, "text": "이 화면에서"}
],
"orange" : [
{"isMe": false, "text": "hey wassup You to party tonight?"},
{"isMe": true, "text": "I wanna go, but nah"},
{"isMe": false, "text": "Why? I heard they prepared a lot. It must be cool"},
{"isMe": true, "text": "My professor just uploaded a new assignment, and the due is tomorrow"},
{"isMe": false, "text": "이름 아래 뜨는 텍스트는"}
],
"yellow" : [
{"isMe": false, "text": "hey wassup You to party tonight?"},
{"isMe": true, "text": "I wanna go, but nah"},
{"isMe": false, "text": "Why? I heard they prepared a lot. It must be cool"},
{"isMe": true, "text": "My professor just uploaded a new assignment, and the due is tomorrow"},
{"isMe": false, "text": "채팅방에서"}
],
"green" : [
{"isMe": false, "text": "hey wassup You to party tonight?"},
{"isMe": true, "text": "I wanna go, but nah"},
{"isMe": false, "text": "Why? I heard they prepared a lot. It must be cool"},
{"isMe": true, "text": "My professor just uploaded a new assignment, and the due is tomorrow"},
{"isMe": false, "text": "마지막으로 한 대화입니다"}
],
"blue" : [
{"isMe": false, "text": "hey wassup You to party tonight?"},
{"isMe": true, "text": "I wanna go, but nah"},
{"isMe": false, "text": "Why? I heard they prepared a lot. It must be cool"},
{"isMe": true, "text": "My professor just uploaded a new assignment, and the due is tomorrow"},
{"isMe": false, "text": "어우 피곤해"}
],
"navy" : [
{"isMe": false, "text": "hey wassup You to party tonight?"},
{"isMe": true, "text": "I wanna go, but nah"},
{"isMe": false, "text": "Why? I heard they prepared a lot. It must be cool"},
{"isMe": true, "text": "My professor just uploaded a new assignment, and the due is tomorrow"},
{"isMe": false, "text": "살려주세요"}
],
"purple" : [
{"isMe": false, "text": "hey wassup You to party tonight?"},
{"isMe": true, "text": "I wanna go, but nah"},
{"isMe": false, "text": "Why? I heard they prepared a lot. It must be cool"},
{"isMe": true, "text": "My professor just uploaded a new assignment, and the due is tomorrow"},
{"isMe": false, "text": "보라색과 한 마지막 대화"}
]
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

json 파일이 깔끔하게 정리된 거 같아요! 그만큼 승범님이 코드를 효율적으로 작성하셨다는 거 같아요.

78 changes: 78 additions & 0 deletions src/ChatListPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import React,{useState} from 'react';
import { initialList } from './App';
import styled from 'styled-components';
import {IoIosText} from 'react-icons/io';
import FriendState from './FriendState';
import {Link} from 'react-router-dom';

const ChatListPageContainer = styled.div`
margin-left: 70px;
`;
const Top = styled.div`
display: flex;
align-items: center;
justify-content: space-between;
`;

const H3 = styled.h3`
padding-left: 10px;
`;
const Icon = styled.div`
padding-right: 10px;
`;

const Input = styled.input`
width: 98%;
margin: 10px;
margin-left: 0px;
height: 30px;
border: solid 1px #dcdcdc;
border-radius: 10%;
display: block;
`;

const StyledLink = styled(Link)`
text-decoration: none;
color: black;
`;


const ChatListPage = () => {
const friendList = initialList;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

App 에서 props로 관리해야 페이지간 데이터 관리가 가능 할 것 같아요

const [text, setText] = useState('');

const onChangeText = (e) => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const onChangeText = (e) => {
const onTextChange = (e) => {

setText(e.target.value);
}

return(
<ChatListPageContainer>
<Top>
<H3>채팅</H3>
<Icon>
<IoIosText size="24" padding-right="10"/>
</Icon>
</Top>
<Input placeholder=" 채팅방, 참여자 검색" value={text} onChange={onChangeText} />
{friendList.map((v) => {
if (text === ''){
return (
<StyledLink to={`/ChattingPage/${v.id}`}>
<FriendState props={v} where={'ChatList'}/>
</StyledLink>
);
} else {
if (v.name.includes(text)){
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

승범님도 includes를 통해서 검색 기능을 구현하셨네요! 저도 이렇게 했는데, 이 방법이 영어로 검색할 때는 대문자까지 그대로 검색해야만 되는 거라 원래의 메신저 검색 기능을 온전히 구현하지 못하는 것 같아요. 그래서 이런 식으로 바꿔주면 어떨까요? 저도 수정하려고 했는데 깜빡한 부분이라 아쉬움이 남아서 코멘트 남겨요.

Suggested change
if (v.name.includes(text)){
if (v.name.toLowerCase().includes(text)){

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

정말 세심한 포인트네요!

return (
<Link to={`/ChattingPage/${v.id}`}>
<FriendState props={v} where={'ChatList'}/>
</Link>
);
}
}
Comment on lines +58 to +72
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (text === ''){
return (
<StyledLink to={`/ChattingPage/${v.id}`}>
<FriendState props={v} where={'ChatList'}/>
</StyledLink>
);
} else {
if (v.name.includes(text)){
return (
<Link to={`/ChattingPage/${v.id}`}>
<FriendState props={v} where={'ChatList'}/>
</Link>
);
}
}
if (text === '' || v.name.includes(text)){
return (
<StyledLink to={`/ChattingPage/${v.id}`}>
<FriendState props={v} where={'ChatList'}/>
</StyledLink>
);
}

위랑 같죠? 심지어 여긴 StyledLink 가 아니라 Link를 써서 검색을 하면 밑줄이 나오네요.
이러한 문제 때문에 동일한 소스코드를 복붙해서 쓰는건 피해야합니다

})}
</ChatListPageContainer>
);
}

export default ChatListPage;
42 changes: 42 additions & 0 deletions src/ChattingPage.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React, { useState, useEffect, useCallback } from 'react';
import Top from './Top';
import Chat from './Chat';
import Form from './Form';
import styled from 'styled-components';
import ChatData from './ChatData.json';
import {initialList} from './App.js';

const ChattingPageContainer = styled.div`
margin-left: 70px;
display: flex;
flex-direction: column;
height: 550px;
`;

const ChattingPage = ({ match }) => {
const [isMe, setIsMe] = useState(true);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

위에서 언급한 것 처럼 id 같은걸 사용하는게 확장성에 용이합니다

const [userName, setUserName] = useState('');
const [chatting, setChatting] = useState([]);

useEffect(() => {
setChatting(ChatData[match.params.id]);
setUserName(initialList.find(e => e.id === match.params.id).name);
}, []);

const onClickTop = useCallback(() => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const onClickTop = useCallback(() => {
const handleTopClick = useCallback(() => {

네이밍은
prop 이름: on + Event
핸들러: on + Component +Event

이 표준이랍니다

setIsMe(!isMe);
}, [isMe]);
const upLoadChatting = useCallback((v) => {
setChatting(v);
}, [])

return (
<ChattingPageContainer>
<Top isMe={isMe} onClickTop={onClickTop} id={match.params.id} userName={userName}/>
<Chat chatting={chatting} isMe={isMe} id={match.params.id}/>
<Form isMe={isMe} upLoadChatting={upLoadChatting} chatting={chatting} />
</ChattingPageContainer>
);
}

export default ChattingPage;
Loading