1- import React , { useEffect , useRef , useState } from 'react' ;
1+ import React , { useEffect , useState , useRef , useMemo } from 'react' ;
22import staticImagePath from '../../constant/staticImagePath' ;
33import styles from './PostItCreate.module.css' ;
44import UnderBarInput from '../../components/UnderBarInput/UnderBarInput' ;
55import BottomButton from '../../components/BottomButton/BottomButton' ;
66import { api } from '../../api/api' ;
77import { useNavigate , useParams } from 'react-router-dom' ;
8+ import { ssrModuleExportsKey } from 'vite/module-runner' ;
9+ import Alert from '../../components/Alert/Alert' ;
810
911export default function PostItCreate ( ) {
1012 const { timepaperId } = useParams ( ) ;
1113 const fileInputRef = useRef ( null ) ;
1214 const [ isSubmitable , setIsSubmitable ] = useState ( false ) ;
1315 const templates = [ staticImagePath . postitAfternoon , staticImagePath . postitNight ] ;
1416 const [ errors , setErrors ] = useState ( { } ) ;
17+ const [ isTouched , setIsTouched ] = useState ( { content : false , authorName : false } ) ;
18+ const [ isShowAlert , setIsShowAlert ] = useState ( false ) ;
19+ const [ alertMessage , setAlertMessage ] = useState ( '' ) ;
1520 const navigate = useNavigate ( ) ;
1621
1722 const INITIAL_FORM_DATA = {
@@ -50,6 +55,10 @@ export default function PostItCreate() {
5055 } ) ) ;
5156 } ;
5257
58+ useEffect ( ( ) => {
59+ setErrors ( validateInput ( inputData ) ) ;
60+ } , [ inputData ] ) ;
61+
5362 const handleStaticImage = ( src ) => ( ) => {
5463 setImageState ( ( prev ) => ( {
5564 ...prev ,
@@ -59,6 +68,13 @@ export default function PostItCreate() {
5968 } ) ) ;
6069 } ;
6170
71+ const handleOnClick = ( e ) => {
72+ const { name } = e . target ;
73+ setIsTouched ( ( prev ) => ( { ...prev , [ name ] : true } ) ) ;
74+ const a = validateInput ( inputData ) ;
75+ setErrors ( a ) ;
76+ } ;
77+
6278 const handleUploadImageClick = ( ) => {
6379 fileInputRef . current . click ( ) ;
6480 } ;
@@ -70,7 +86,8 @@ export default function PostItCreate() {
7086
7187 const validImageTypes = [ 'image/jpeg' , 'image/png' , 'image/gif' ] ;
7288 if ( ! validImageTypes . includes ( file . type ) ) {
73- alert ( '이미지 파일만 업로드 가능합니다.' ) ;
89+ setIsShowAlert ( true ) ;
90+ setAlertMessage ( '이미지 파일만 업로드 가능합니다.' ) ;
7491 return ;
7592 }
7693
@@ -86,10 +103,6 @@ export default function PostItCreate() {
86103 reader . readAsDataURL ( file ) ;
87104 } ;
88105
89- const handleBlur = ( ) => {
90- setErrors ( validateInput ( inputData ) ) ;
91- } ;
92-
93106 const validateInput = ( data ) => {
94107 const errors = { } ;
95108 let isValid = true ;
@@ -151,42 +164,54 @@ export default function PostItCreate() {
151164 formData . append ( 'image' , imageState . imageData ) ;
152165 }
153166
167+ setIsSubmitable ( false ) ;
154168 ( async ( ) => {
155169 try {
156170 const response = await api . createPostit ( timepaperId , formData ) ;
157171 if ( response . status === 201 ) {
158172 navigate ( `/timepaper/${ timepaperId } ` , { replace : true } ) ;
159173 }
160174 } catch ( error ) {
161- alert ( '등록에 실패했습니다.' ) ;
162- } finally {
163- setIsSubmitable ( false ) ;
175+ setIsShowAlert ( true ) ;
176+ setAlertMessage ( '등록에 실패했습니다.' ) ;
177+ setIsSubmitable ( true ) ;
164178 }
165179 } ) ( ) ;
166180 } ;
167181
182+ const handleAlertButtonClick = ( ) => {
183+ setIsShowAlert ( false ) ;
184+ } ;
185+
168186 return (
169187 < >
188+ { isShowAlert && (
189+ < Alert message = { alertMessage } buttonTitle = { '확인' } onClick = { handleAlertButtonClick } > </ Alert >
190+ ) }
170191 < form action = "" className = { styles . container } >
171192 < div className = { styles . underBarInput } >
172193 < UnderBarInput
173194 onChange = { handleOnChange }
174195 name = "authorName"
175196 placeholder = "작성자 입력"
176- onBlur = { handleBlur }
197+ onClick = { handleOnClick }
177198 > </ UnderBarInput >
178- { errors . authorName && < p className = { styles . error } > { errors . authorName } </ p > }
199+ { isTouched . authorName && errors . authorName && (
200+ < p className = { styles . error } > { errors . authorName } </ p >
201+ ) }
179202 </ div >
180203 < div className = { styles . selectedImage } >
181204 < img src = { imageState . preview } className = "logo-image" alt = "선택된 포스트잇 이미지" />
182205 < div className = { styles . textareaContainer } >
183206 < textarea
184207 onChange = { handleOnChange }
185- onBlur = { handleBlur }
186208 name = "content"
187209 className = { styles . textarea }
210+ onClick = { handleOnClick }
188211 > </ textarea >
189- { errors . content && < p className = { styles . textareaError } > { errors . content } </ p > }
212+ { isTouched . content && errors . content && (
213+ < p className = { styles . textareaError } > { errors . content } </ p >
214+ ) }
190215 </ div >
191216 </ div >
192217 < section className = { styles . imageContainer } >
0 commit comments