-
Notifications
You must be signed in to change notification settings - Fork 1
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
채팅 입력 글자수 제한 #363
채팅 입력 글자수 제한 #363
Changes from all commits
30cf354
e764890
e5b9b26
5ba154f
45ab569
39e9029
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,33 +1,34 @@ | ||
import styled from "@emotion/styled"; | ||
import TextareaAutosize from "react-textarea-autosize"; | ||
import { w, h, text, padding } from "@/styles"; | ||
|
||
export const TextAreaFixedsize = styled.textarea` | ||
width: 100%; | ||
height: 100%; | ||
padding: 10px 15px; | ||
${w("fill")} | ||
${h("fill")} | ||
${padding.vertical(10)} | ||
${padding.horizontal(15)} | ||
resize: none; | ||
border: none; | ||
background: transparent; | ||
font-size: 11px; | ||
font-weight: 500; | ||
color: ${props => props.theme.colors.black}; | ||
${text.subtitle} | ||
${text.black} | ||
::placeholder { | ||
font-family: "Noto Sans KR", sans-serif; | ||
color: ${props => props.theme.colors.gray300}; | ||
${text.gray300} | ||
} | ||
`; | ||
|
||
export const TextAreaAutosize = styled(TextareaAutosize)` | ||
width: 100%; | ||
${w("fill")} | ||
max-height: 100%; | ||
outline: none; | ||
resize: none; | ||
border: none; | ||
background: transparent; | ||
font-size: 12px; | ||
font-weight: 500; | ||
color: ${props => props.theme.colors.black}; | ||
${text.body} | ||
${text.black} | ||
::placeholder { | ||
font-family: "Noto Sans KR", sans-serif; | ||
color: ${props => props.theme.colors.gray300}; | ||
${text.gray300} | ||
} | ||
`; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,20 +1,49 @@ | ||
import React, { useCallback, useMemo } from "react"; | ||
import styled from "@emotion/styled"; | ||
import { css } from "@emotion/react"; | ||
|
||
import { EmoticonIcon, SendIcon } from "@/assets"; | ||
import { Box, Divider, TextAreaAutosize } from "@/components/atoms"; | ||
import { Divider, TextAreaAutosize } from "@/components/atoms"; | ||
import { useInput } from "@/common/hooks"; | ||
import { | ||
w, | ||
h, | ||
padding, | ||
scroll, | ||
scrollBar, | ||
bg, | ||
justify, | ||
align, | ||
row, | ||
gap, | ||
border, | ||
round, | ||
} from "@/styles"; | ||
|
||
const InputForm = styled.form` | ||
display: flex; | ||
flex-direction: row; | ||
gap: 10px; | ||
width: 100%; | ||
height: 100%; | ||
padding: 10px 15px; | ||
background-color: ${props => props.theme.colors.white}; | ||
border: solid 1px ${props => props.theme.colors.gray300}; | ||
border-radius: 5px; | ||
const inputBoxStyle = css` | ||
${w("fill")} | ||
max-height: 30%; | ||
${padding(10)} | ||
${bg.white100} | ||
${justify.start} | ||
${align.start} | ||
`; | ||
|
||
const formStyle = css` | ||
${row} | ||
${gap(10)} | ||
${w("fill")} | ||
${h("fill")} | ||
${padding.vertical(10)} | ||
${padding.horizontal(15)} | ||
${bg.white} | ||
${border.gray300} | ||
${round.md} | ||
`; | ||
|
||
const textAreaScrollStyle = css` | ||
${scroll.y} | ||
${scrollBar} | ||
overflow-y: scroll; | ||
`; | ||
|
||
interface Props { | ||
|
@@ -24,37 +53,44 @@ interface Props { | |
export const ChatInput: React.FC<Props> = ({ send }) => { | ||
const { input, setValue } = useInput(); | ||
|
||
// TODO: disable send button based on `validated` | ||
/** TODO: disable send button based on `validated` */ | ||
const validated = useMemo(() => input.value.trim().length > 0, [input.value]); | ||
|
||
/** @constant 클라이언트와 서버에서 사용하는 채팅 메시지의 최대 길이를 지정합니다. */ | ||
const maxMessageLength = 500; | ||
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. 서버, 클라이언트에서 모두 사용하는 값이라서 interface에 저장할 수 있으면 좋겠다고 생각했습니다! |
||
|
||
const sendCurrent = useCallback(() => { | ||
if (!validated) return; | ||
send(input.value.trim()); | ||
setValue(""); | ||
}, [input.value, validated]); | ||
|
||
return ( | ||
<Box w="fill" pad={10} bg="white100"> | ||
<InputForm> | ||
<TextAreaAutosize | ||
onKeyDown={e => { | ||
if ( | ||
e.key === "Enter" && | ||
!e.shiftKey && | ||
!e.nativeEvent.isComposing | ||
) { | ||
e.preventDefault(); | ||
sendCurrent(); | ||
} | ||
}} | ||
value={input.value} | ||
onChange={input.onChange} | ||
/> | ||
<Divider dir="vertical" /> | ||
<div css={inputBoxStyle}> | ||
<form css={formStyle}> | ||
<div css={[row, w("fill"), h("fill")]}> | ||
<TextAreaAutosize | ||
css={textAreaScrollStyle} | ||
onKeyDown={e => { | ||
if ( | ||
e.key === "Enter" && | ||
!e.shiftKey && | ||
!e.nativeEvent.isComposing | ||
) { | ||
e.preventDefault(); | ||
sendCurrent(); | ||
} | ||
}} | ||
value={input.value} | ||
maxLength={maxMessageLength} | ||
onChange={input.onChange} | ||
/> | ||
<Divider dir="vertical" /> | ||
</div> | ||
<EmoticonIcon /> | ||
<SendIcon onClick={sendCurrent} /> | ||
{/* TODO: Replace with button / add hover, actove effect */} | ||
</InputForm> | ||
</Box> | ||
</form> | ||
</div> | ||
); | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,10 +32,10 @@ export type AdminAgenda = z.infer<typeof AdminAgenda>; | |
* some description about admin agenda create schema goes here | ||
*/ | ||
export const AdminAgendaCreate = z.object({ | ||
title: z.string().min(1), | ||
content: z.string().min(1), | ||
resolution: z.string().min(1), | ||
choices: z.array(z.string().min(1)).min(1), | ||
title: z.string().min(1).max(255), | ||
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. mysql에서 string 자료형의 길이는 [0, 255]입니다. 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. 그래서 max 255였군용 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. 저도 처음 알았어요! |
||
content: z.string().min(1).max(255), | ||
resolution: z.string().min(1).max(255), | ||
choices: z.array(z.string().min(1).max(255)).min(1), | ||
voters: z.object({ | ||
total: z.array(z.number()), | ||
}), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,11 +20,11 @@ export type AgendaTemplate = z.infer<typeof AgendaTemplate>; | |
* some description about agenda template create schema goes here | ||
*/ | ||
export const AgendaTemplateCreate = z.object({ | ||
templateName: z.string(), | ||
title: z.string(), | ||
content: z.string(), | ||
resolution: z.string(), | ||
choices: z.array(z.string()), | ||
templateName: z.string().min(1).max(255), | ||
title: z.string().min(1).max(255), | ||
content: z.string().min(1).max(255), | ||
resolution: z.string().min(1).max(255), | ||
choices: z.array(z.string().min(1).max(255)), | ||
Comment on lines
+23
to
+27
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. 우와 추가했습니다! 감사합니다! |
||
}); | ||
export type AgendaTemplateCreate = z.infer<typeof AgendaTemplateCreate>; | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ import { Message } from "./common"; | |
* description | ||
*/ | ||
export const Send = z.object({ | ||
message: z.string().min(1), | ||
message: z.string().min(1).max(500), | ||
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. 클라이언트가 채팅을 보내는 이벤트에서는 이 |
||
}); | ||
export type Send = z.infer<typeof Send>; | ||
export const SendCb = Message; | ||
|
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.
overflow: scroll
대신overflow: auto
를 사용하면 스크롤바가 보일 때와 보이지 않을 때 텍스트 영역의 너비가 달라집니다.