Skip to content

[5주차] 정대헌 미션 제출합니다. #20

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

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open
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
598 changes: 583 additions & 15 deletions package-lock.json

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,27 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@reduxjs/toolkit": "^1.8.1",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^13.5.0",
"@types/jest": "^27.5.0",
"@types/node": "^17.0.31",
"@types/react": "^18.0.8",
"@types/react-dom": "^18.0.3",
"@types/react-redux": "^7.1.24",
"@types/redux": "^3.6.0",
"@types/redux-thunk": "^2.1.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
"react-icons": "^4.3.1",
"react-redux": "^8.0.1",
"react-router-dom": "^6.3.0",
"react-scripts": "5.0.1",
"redux-thunk": "^2.4.1",
"styled-components": "^5.3.5",
"typescript": "^4.6.4",
"uuid": "^8.3.2",
"web-vitals": "^2.1.4"
},
"scripts": {
Expand All @@ -34,5 +49,9 @@
"last 1 firefox version",
"last 1 safari version"
]
},
"devDependencies": {
"@types/styled-components": "^5.1.25",
"@types/uuid": "^8.3.4"
}
}
5 changes: 0 additions & 5 deletions src/App.js

This file was deleted.

34 changes: 34 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import React from "react";
import { Outlet } from "react-router-dom";
import styled from "styled-components";

import SideButtonContainer from "./containers/SideButtonContainer";

const AppContainer = styled.div`
display: flex;
flex-direction: row;
Copy link
Member

Choose a reason for hiding this comment

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

flex-direction의 default가 row라 이 부분은 생략해도 되지 않을까요?!

Copy link
Author

Choose a reason for hiding this comment

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

맞아요~ 본능적으로 쓰게되는.. 실수입니다.

align-items: center;
justify-content: center;
width: 100%;
height: 100vh;
font-family: var(--ff-main);
`

const EmptyDiv = styled.div`
width: 5rem;
height: 3rem;
margin-left: 1rem;
flex: 1;
`

function App() {

return (
<AppContainer>
<SideButtonContainer/>
<Outlet/>
<EmptyDiv/>
</AppContainer>);
}

export default App;
27 changes: 27 additions & 0 deletions src/GlobalStyle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import {createGlobalStyle} from "styled-components";

export default createGlobalStyle`
@import url("https://fonts.googleapis.com/css2?family=Noto+Sans+KR&display=swap");

:root{
--ff-main: "Noto Sans KR", sans-serif;
}

*,
::after,
::before {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body{
display: flex;
height: 100vh;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: #f0f0f0;
background-image: linear-gradient(45deg, #ff9a9e 0%, #fad0c4 99%, #fad0c4 100%);
}
`;
94 changes: 94 additions & 0 deletions src/components/ChatButtonComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
import React from 'react'
import styled from 'styled-components'

import { useAppDispatch, useAppSelector } from '../hooks'
import { useNavigate } from 'react-router-dom'
import { setActiveChat } from '../state/chatSlice'
import { Chat } from '../types'

const Component = styled.button`
width: 80%;
display: flex;
flex-direction: column;
align-content: flex-start;
justify-content: flex-start;
border-radius: 3rem;
background-color: rgba(255, 255, 255, 0.5);
margin: 1rem 0 1rem 0;
border: transparent;
padding: 0 2rem 0.5rem 2rem;
cursor: pointer;
&:hover {
box-shadow: 0px 0px 20px rgba(230, 230, 230, 1);
}
`
const ProfileDiv = styled.div`
width: 100%;
display: flex;
justify-content: flex-start;
height: 3rem;
align-items: center;
`

const NameDiv = styled.div`
background-color: rgba(255, 255, 255, 1);
border-radius: 3rem;
padding: 0.3rem 1rem 0.3rem 1rem;
margin-left: 0.5rem;
text-transform: lowercase;
color: rgb(130, 130, 130);
font-size: 1rem;
box-shadow: 0px 5px 10px rgba(230, 230, 230, 0.3);
`
const MessageDiv = styled.div`
width: 100%;
display: flex;
justify-content: space-between;
padding: 0.3rem 1rem 0.3rem 1rem;
text-transform: lowercase;
color: rgb(130, 130, 130);
font-size: 1.3rem;
box-shadow: 0px 5px 10px rgba(230, 230, 230, 0.3);
`

const TimeP = styled.p`
font-size: 1rem;
`

const ProfileImage = styled.img`
position: relative;
bottom: 1rem;
width: 4rem;
height: 4rem;
object-fit: cover;
`

function ChatButtonComponent({chat}:{chat:Chat}) {

const dispatch = useAppDispatch();
const navigate = useNavigate();
const clients = useAppSelector((state)=>state.client.clients);

return (
<Component onClick={()=>{
dispatch(setActiveChat(chat.chatId));
navigate(`/chats/${chat.chatId}`);
}}>
Comment on lines +73 to +76
Copy link
Member

Choose a reason for hiding this comment

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

개인적인 생각으로는 코드가 두 줄 이상으로 길어지게 되면 함수로 빼는게 좋을 것 같아요!

Copy link
Author

Choose a reason for hiding this comment

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

맞습니다, 참조하도록 하겠습니다!

{chat.clients.map((client)=>{
if(client.id !== clients[0].id)
return(
<ProfileDiv key={chat.chatId}>
<ProfileImage src={client.imageUrl}/>
<NameDiv>{client.name}</NameDiv>
</ProfileDiv>
)
})}
Comment on lines +77 to +85
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
{chat.clients.map((client)=>{
if(client.id !== clients[0].id)
return(
<ProfileDiv key={chat.chatId}>
<ProfileImage src={client.imageUrl}/>
<NameDiv>{client.name}</NameDiv>
</ProfileDiv>
)
})}
{chat.clients.map(
(client) =>
client.id !== clients[0].id && (
<ProfileDiv key={chat.chatId}>
<ProfileImage src={client.imageUrl} />
<NameDiv>{client.name}</NameDiv>
</ProfileDiv>
)
)}

&&연산자 사용하고 return문도 생략해주면 조금 더 간단하게 작성할 수 있지 않을까요??

Copy link
Author

Choose a reason for hiding this comment

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

&& 연산자가 익숙하지 않은데, 보기 더 간편해지는 것 같아요. 좋습니다~

<MessageDiv>
<>{chat.messages[chat.messages.length-1]? chat.messages[chat.messages.length-1].content : ""}</>
<TimeP>{chat.messages[chat.messages.length-1]? chat.messages[chat.messages.length-1].timeString : ""}</TimeP>
</MessageDiv>
</Component>
)
}

export default ChatButtonComponent
93 changes: 93 additions & 0 deletions src/components/MessageBubbleComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import styled from 'styled-components'

import { Message, MessageType } from '../types'

const componentPadding = {
[MessageType.BASE]: "0.5rem 1rem 0.5rem 1rem",
[MessageType.HEAD]: "0.5rem 1rem 0rem 1rem",
[MessageType.BODY]: "0rem 1rem 0rem 1rem",
[MessageType.TAIL]: "0rem 1rem 0.5rem 1rem",
}

const bubbleRadiusSelected = {
[MessageType.BASE]: "1rem",
[MessageType.HEAD]: "1rem 1rem 0.3rem 1rem",
[MessageType.BODY]: "1rem 0.3rem 0.3rem 1rem",
[MessageType.TAIL]: "1rem 0.3rem 1rem 1rem",
}
const bubbleRadiusDeselected = {
[MessageType.BASE]: "1rem",
[MessageType.HEAD]: "1rem 1rem 1rem 0.3rem",
[MessageType.BODY]: "0.3rem 1rem 1rem 0.3rem",
[MessageType.TAIL]: "0.3rem 1rem 1rem 1rem",
}


const Component = styled.div<{selected: boolean, manner: MessageType}>`
width: 100%;
display: flex;
flex-direction: ${({selected})=>(selected? "row-reverse":"row")};
padding: ${({manner})=>componentPadding[manner]};
`
const MessageProfileImg = styled.img`
width: 3rem;
height: 3rem;
object-fit: contain;
`
const MessageProfileDiv = styled.div`
width: 3rem;
height: 3rem;
`
const MessageContentDiv = styled.div`
width: 30vw;
max-width: 20rem;
margin-left: 1rem;
margin-right: 1rem
`
const Name = styled.p<{selected: boolean}>`
font-size: 0.8rem;
text-align: ${({selected})=>(selected? "right":"left")};
`

const MessageHolderDiv = styled.div<{selected: boolean}>`
width: 100%;
display: flex;
flex-direction: ${({selected})=>(selected? "row-reverse":"row")};
align-items: flex-end;
`

const MessageBubbleDiv = styled.div<{selected: boolean, manner: MessageType}>`
max-width: calc(100% - 4rem);
height: 100%;
background-color: ${({selected})=>(selected? "#ff9a9e":"#ffecd2")};
border-radius: ${({selected, manner})=>(selected? bubbleRadiusSelected[manner]:bubbleRadiusDeselected[manner])};
Copy link
Member

Choose a reason for hiding this comment

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

오 이런 방법을 사용해서 메시지 꼬리를 다르게 표현할 수 있군요!! 너무 좋습니다👍

Copy link
Author

Choose a reason for hiding this comment

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

감사합니다~

padding: 0.8rem;
margin-top: 0.2rem;
color: ${({selected})=>(selected? "white":"black")};
word-wrap: break-word;
`
const Time = styled.p`
font-size: 0.6rem;
margin-left: 0.3rem;
margin-right: 0.3rem;
`

const MessageBubbleComponent = ({msg, timeString, selected, manner}: {msg:Message, timeString:string, selected:boolean, manner:MessageType}) => {

return(
<Component selected={selected} manner={manner}>
<MessageProfileDiv>
{manner === MessageType.BASE || manner === MessageType.HEAD? <MessageProfileImg src={msg.client.imageUrl}/> : "" }
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
{manner === MessageType.BASE || manner === MessageType.HEAD? <MessageProfileImg src={msg.client.imageUrl}/> : "" }
{(manner === MessageType.BASE || manner === MessageType.HEAD) && (
<MessageProfileImg src={msg.client.imageUrl} />
)}

이부분도 &&연산자 사용하면 더 간략하게 적을 수 있을 것 같아요~!

Copy link
Author

Choose a reason for hiding this comment

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

넵, 감사합니다!

</MessageProfileDiv>
<MessageContentDiv>
{manner === MessageType.BASE || manner === MessageType.HEAD? <Name selected={selected}>{msg.client.name}</Name> : "" }
<MessageHolderDiv selected={selected}>
<MessageBubbleDiv selected={selected} manner={manner}><p>{msg.content}</p></MessageBubbleDiv>
{manner === MessageType.BASE || manner === MessageType.TAIL? <Time>{timeString}</Time> : "" }
</MessageHolderDiv>
</MessageContentDiv>
</Component>
)
}

export default MessageBubbleComponent;
Loading