@@ -53,10 +53,9 @@ const AvatarOption = styled.div`
5353
5454const AvatarPreview = styled . div `
5555 cursor: pointer;
56- ` ;
57-
58- const DefaultAvatar = styled . div `
59- cursor: pointer;
56+ box-shadow: ${ ( { $isSelected } ) =>
57+ $isSelected ? `0 0 0 2px ${ Colors . purple ( 600 ) } ` : "none" } ;
58+ border-radius: 50%;
6059` ;
6160
6261const ButtonWrapper = styled . div `
@@ -69,13 +68,20 @@ const CreateButton = styled(PrimaryButton)`
6968 width: 100%;
7069` ;
7170
71+ const TextFieldStyle = styled ( TextField ) `
72+ width: 50%;
73+ ` ;
74+
7275function SendMessagePage ( ) {
7376 const [ name , setName ] = useState ( "" ) ;
7477 const [ nameError , setNameError ] = useState ( "" ) ;
7578 const [ relationOption , setRelationOption ] = useState ( "지인" ) ;
7679 const [ selectedAvatar , setSelectedAvatar ] = useState ( null ) ;
7780 const [ content , setContent ] = useState ( "I am your reach text editor." ) ;
78- const [ fontOption , setFontOption ] = useState ( "Noto Sans" ) ;
81+ const [ selectedFont , setSelectedFont ] = useState ( {
82+ title : "Noto Sans" ,
83+ fontFamily : "Noto Sans" ,
84+ } ) ;
7985 const navigate = useNavigate ( ) ;
8086
8187 const handleChange = ( e ) => {
@@ -88,33 +94,43 @@ function SendMessagePage() {
8894 }
8995 } ;
9096
97+ const trimmed = name . trim ( ) ;
98+
9199 const handleBlur = ( ) => {
92- if ( name . trim ( ) === "" ) {
93- setNameError ( "값을 입력해 주세요" ) ;
94- } else if ( name !== name . trim ( ) ) {
95- setNameError ( "공백 없이 입력해 주세요" ) ; // 텍스트 앞 뒤 공백 에러 처리(임시)
100+ setName ( trimmed ) ;
101+ if ( trimmed === "" ) {
102+ setNameError ( "이름을 입력해 주세요" ) ;
96103 }
97104 } ;
98105
99106 const avatarList = [
100- "https://i.pinimg. com/236x/49/86/62/4986627b45cecd1a5c4330bda777c2bf.jpg " ,
101- "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRok3sjZOWtm7o5kFf0BdW0w7IUHI1oAlC-Z6RCKAiCvvCExG_qq7qMzPOQlEzfknS3B3U&usqp=CAU " ,
102- "https://i.pinimg.com/236x/20/d1/6f/20d16f236500e8daa315a298a8586193.jpg " ,
103- "https://i.pinimg.com/474x/28/6c/fd/286cfdcdaeaf2768d4b285a226c33a02.jpg " ,
104- "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRvxR-Twic2lXwfF87JweyQ81vrGDUgn7zzYj60N-wD21DwS4JzOc0BLhzaOuUt4PGfLcI&usqp=CAU " ,
105- "https://i.pinimg.com/236x/74/68/89/7468894ce7592357a3514dbb8dc5f181.jpg " ,
106- "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMjE1/MDAxNjMwNTk5NjE4NTc5.b-OgHjcav5kz8kt_9Cr2u1Z_eJYmKY_H9Ii9mOnwo74g.r0G6iGYg-oQMLnTymwyrjDlOMGLEnWGYJXefCSy2ixwg.JPEG.gmlwjd5363/FB_IMG_1630599533529.jpg?type=w800 " ,
107- "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMTIy/MDAxNjMwNTk5NjE5MDA5.w_wMeYmMF2kOhDAVXXxe0JgVqJhtGd0EuR0b2D2k3S0g.Nds6Oxagjks2DjjwFz5yWyjCGcEOL1iS84XqhAQw3wUg.JPEG.gmlwjd5363/FB_IMG_1630599535069.jpg?type=w800 " ,
108- "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfNDQg/MDAxNjMwNTk5NjE5MzQ4.J4lhtJZRKMzEXj0HjrG1aH65qIcBv9GI1LdVQsWlC-Ug.10QCNt81CdbIyBkd1bFOAOAolDL6hxYXrb9dXgmS8zQg.JPEG.gmlwjd5363/FB_IMG_1630599536666.jpg?type=w800 " ,
109- "https://mblogthumb-phinf.pstatic.net/MjAyMTA5MDNfMzAg/MDAxNjMwNTk5NjE5ODI2.cmwNyDHTza4N64bhN0rIRu2KaFHUxqv0BkuaX6GBHJ0g.ufZqe7x1GLrCLJg2zb6N_nJ_fTgFPXq09TTe_fhsMiog.JPEG.gmlwjd5363/FB_IMG_1630599538261.jpg?type=w800 " ,
107+ "https://learn-codeit-kr-static.s3.ap-northeast-2.amazonaws. com/sprint-proj-image/default_avatar.png " ,
108+ "https://picsum.photos/id/522/100/100 " ,
109+ "https://picsum.photos/id/547/100/100 " ,
110+ "https://picsum.photos/id/268/100/100 " ,
111+ "https://picsum.photos/id/1082/100/100 " ,
112+ "https://picsum.photos/id/571/100/100 " ,
113+ "https://picsum.photos/id/494/100/100 " ,
114+ "https://picsum.photos/id/859/100/100 " ,
115+ "https://picsum.photos/id/437/100/100 " ,
116+ "https://picsum.photos/id/1064/100/100 " ,
110117 ] ;
111118
112119 const handleCreate = ( ) => {
113120 const randomID = Math . floor ( Math . random ( ) * 10000 ) ;
114121 navigate ( `/post/${ randomID } ` ) ;
115122 } ;
116123
117- const canCreate = name . trim ( ) !== "" ;
124+ const canCreate =
125+ trimmed !== "" && content . replace ( / < [ ^ > ] + > / g, "" ) . trim ( ) !== "" ;
126+ // 정규식 유효성 검사로 html 태그 찾기("<"로 시작해서 ">"로 끝나는 문자 중 > 를 제외한(^ not) 모든 문자 제외)
127+
128+ const fontOptions = [
129+ { title : "Noto Sans" , fontFamily : "Noto Sans" } ,
130+ { title : "Pretendard" , fontFamily : "Pretendard" } ,
131+ { title : "나눔고딕" , fontFamily : "Nanum Ghthic" } ,
132+ { title : "나눔손글씨 펜체" , fontFamily : "Nanum Pen Script" } ,
133+ ] ;
118134
119135 return (
120136 < SendContainer >
@@ -132,11 +148,7 @@ function SendMessagePage() {
132148 < Wrapper >
133149 < SendTitle > 프로필 이미지</ SendTitle >
134150 < AvatarWrapper >
135- < DefaultAvatar
136- onClick = { ( ) => setSelectedAvatar ( ( prev ) => ( prev ? null : prev ) ) } // 아바타 선택 상태에서 재클릭 시 기본 아바타로
137- >
138- < Avatar size = { AVATAR_SIZE . large } source = { selectedAvatar } />
139- </ DefaultAvatar >
151+ < Avatar size = { AVATAR_SIZE . large } source = { selectedAvatar } />
140152 < AvatarOptionWrapper >
141153 < AvatarDescription >
142154 프로필 이미지를 선택해 주세요!
@@ -145,6 +157,7 @@ function SendMessagePage() {
145157 { avatarList . map ( ( url , index ) => (
146158 < AvatarPreview
147159 key = { index }
160+ $isSelected = { selectedAvatar === url }
148161 onClick = { ( ) => setSelectedAvatar ( url ) }
149162 >
150163 < Avatar size = { AVATAR_SIZE . medium } source = { url } />
@@ -156,7 +169,7 @@ function SendMessagePage() {
156169 </ Wrapper >
157170 < Wrapper >
158171 < SendTitle > 상대와의 관계</ SendTitle >
159- < TextField
172+ < TextFieldStyle
160173 type = { TEXT_FIELD_TYPE . dropdown }
161174 dropdownId = "realtionship-dropdown"
162175 placeholder = { relationOption }
@@ -176,24 +189,25 @@ function SendMessagePage() {
176189 } }
177190 value = { content }
178191 onChange = { ( value ) => setContent ( value ) }
179- font = { fontOption }
192+ font = { selectedFont . fontFamily }
180193 />
181194 </ div >
182195 </ Wrapper >
183196 < Wrapper >
184197 < SendTitle > 폰트 선택</ SendTitle >
185- < TextField
198+ < TextFieldStyle
186199 type = { TEXT_FIELD_TYPE . dropdown }
187200 dropdownId = "font-option-dropdown"
188- placeholder = { fontOption }
189- value = { fontOption }
190- options = { [
191- "Noto Sans" ,
192- "Pretendard" ,
193- "Nanum Gothic" ,
194- "Nanum Pen Script" ,
195- ] }
196- onSelect = { setFontOption }
201+ placeholder = { selectedFont . title }
202+ value = { selectedFont . title }
203+ options = { fontOptions }
204+ onSelect = { ( selectedFontOption ) => {
205+ const selected = fontOptions . find (
206+ ( fontOption ) => fontOption . title === selectedFontOption
207+ ) ;
208+ setSelectedFont ( selected ) ;
209+ } }
210+ style = { { fontFamily : selectedFont . fontFamily } }
197211 />
198212 </ Wrapper >
199213 < ButtonWrapper >
0 commit comments