-
Notifications
You must be signed in to change notification settings - Fork 10
[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
base: main
Are you sure you want to change the base?
Changes from all commits
4abceae
88d174c
17ea155
62e29cc
e66d3ea
7cd3498
f571c04
5e2ab25
459f5f6
d65c56f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
This file was deleted.
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; | ||
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; |
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%); | ||
} | ||
`; |
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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 개인적인 생각으로는 코드가 두 줄 이상으로 길어지게 되면 함수로 빼는게 좋을 것 같아요! There was a problem hiding this comment. Choose a reason for hiding this commentThe 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
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
&&연산자 사용하고 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 |
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])}; | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오 이런 방법을 사용해서 메시지 꼬리를 다르게 표현할 수 있군요!! 너무 좋습니다👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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}/> : "" } | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
이부분도 &&연산자 사용하면 더 간략하게 적을 수 있을 것 같아요~! There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
flex-direction
의 default가row
라 이 부분은 생략해도 되지 않을까요?!There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
맞아요~ 본능적으로 쓰게되는.. 실수입니다.