@@ -2,6 +2,12 @@ import {
22 useGetArticleDetail ,
33 useGetModalCategories ,
44} from '@/pages/dashboard/apis/query/article' ;
5+ import {
6+ usePatchCategories ,
7+ useDeleteCategories ,
8+ usePatchArticles ,
9+ usePostCategories ,
10+ } from '@/pages/dashboard/apis/query/category' ;
511import { fetchOGData } from '@/shared/utils/ogImage' ;
612import { POP_TEXTAREA_MAX_LENGTH } from '@constants/index' ;
713import {
@@ -39,16 +45,25 @@ const ModalPop = ({ onClose, onDelete, selectedArticleId }: ModalPopProps) => {
3945 const [ categoryPopupMode , setCategoryPopupMode ] = useState <
4046 'edit' | 'add' | ''
4147 > ( '' ) ;
48+ const [ memo , setMemo ] = useState ( '' ) ;
4249 const [ categories , setCategories ] = useState < string [ ] > ( [ ] ) ;
50+
4351 const [ selectedCategory , setSelectedCategory ] = useState ( '' ) ;
4452 const { data : modalCategories } = useGetModalCategories ( ) ; // 모달 카테고리 전체 조회
4553 const { data : articleDetail } = useGetArticleDetail ( selectedArticleId ) ; // 아티클 상세 조회
54+ const { mutate : patchCategories } = usePatchCategories ( ) ; // 카테고리 수정
55+ const { mutate : deleteCategories } = useDeleteCategories ( ) ; // 카테고리 삭제
56+ const { mutate : postCategories } = usePostCategories ( ) ;
4657 const [ matchId , setMatchedId ] = useState < number | null > ( null ) ;
58+ const [ editCategoryIndex , setEditCategoryIndex ] = useState < number | null > (
59+ null
60+ ) ;
61+ const { mutate : patchArticle } = usePatchArticles ( ) ;
62+ const [ url , setUrl ] = useState ( '' ) ;
4763 const [ title , setTitle ] = useState ( '' ) ;
4864 const [ description , setDescription ] = useState ( '' ) ;
4965 const [ image , setImage ] = useState ( '' ) ;
50-
51- console . log ( 'matchId' , matchId ) ; // TODO: 일단 안 쓰는데 재림쓰 필요할 거 같아서 남김ㅎ
66+ const [ articleId , setArticleId ] = useState ( 0 ) ;
5267
5368 const handleFieldChange = (
5469 field : 'date' | 'time' ,
@@ -62,8 +77,10 @@ const ModalPop = ({ onClose, onDelete, selectedArticleId }: ModalPopProps) => {
6277 } ) ) ;
6378 } ;
6479
65- const handleCategoryChange = ( value : string ) => {
80+ const handleCategoryChange = ( value : string , index ?: number ) => {
6681 if ( value === 'edit' ) {
82+ setEditCategoryIndex ( index ?? null ) ;
83+ setSelectedCategory ( value ) ;
6784 setCategoryPopupMode ( 'edit' ) ;
6885 } else if ( value === 'create' ) {
6986 setCategoryPopupMode ( 'add' ) ;
@@ -82,8 +99,19 @@ const ModalPop = ({ onClose, onDelete, selectedArticleId }: ModalPopProps) => {
8299 return ;
83100 }
84101 if ( categoryPopupMode === 'add' ) {
85- setCategories ( ( prev ) => [ ...prev , newCategory ] ) ;
86- setSelectedCategory ( newCategory ) ;
102+ postCategories (
103+ { categoryName : newCategory } ,
104+ {
105+ onSuccess : ( ) => {
106+ setCategories ( ( prev ) => [ ...prev , newCategory ] ) ;
107+ setSelectedCategory ( newCategory ) ;
108+ handlePopupClose ( ) ;
109+ } ,
110+ onError : ( err : any ) => {
111+ console . log ( err ) ;
112+ } ,
113+ }
114+ ) ;
87115 } else if ( categoryPopupMode === 'edit' ) {
88116 setCategories ( ( prev ) =>
89117 prev . map ( ( cat ) => ( cat === selectedCategory ? newCategory : cat ) )
@@ -93,6 +121,100 @@ const ModalPop = ({ onClose, onDelete, selectedArticleId }: ModalPopProps) => {
93121 handlePopupClose ( ) ;
94122 } ;
95123
124+ const handlePopupEdit = ( newCategory ?: string ) => {
125+ if ( ! newCategory ) {
126+ return ;
127+ }
128+ if ( categoryPopupMode === 'edit' && editCategoryIndex !== null ) {
129+ setSelectedCategory ( newCategory ) ;
130+ handlePopupClose ( ) ;
131+
132+ patchCategories (
133+ {
134+ categoryId :
135+ modalCategories . data . categories [ editCategoryIndex ] . categoryId ,
136+ categoryName : newCategory ,
137+ } ,
138+ {
139+ onSuccess : ( ) => {
140+ setCategories ( ( prev ) => [ ...prev , newCategory ] ) ;
141+ setSelectedCategory ( newCategory ) ;
142+ location . reload ( ) ;
143+ handlePopupClose ( ) ;
144+ } ,
145+ onError : ( err : Error ) => {
146+ console . log ( err ) ;
147+ } ,
148+ }
149+ ) ;
150+ }
151+ } ;
152+ const handlePopupDelete = ( ) => {
153+ setSelectedCategory ( '' ) ;
154+ if ( categoryPopupMode === 'edit' && editCategoryIndex !== null ) {
155+ handlePopupClose ( ) ;
156+ deleteCategories (
157+ {
158+ categoryId :
159+ modalCategories . data . categories [ editCategoryIndex ] . categoryId ,
160+ } ,
161+ {
162+ onSuccess : ( ) => {
163+ location . reload ( ) ;
164+ handlePopupClose ( ) ;
165+ } ,
166+ onError : ( err : any ) => {
167+ console . error ( err ) ;
168+ } ,
169+ }
170+ ) ;
171+ }
172+ } ;
173+ const handleSave = ( ) => {
174+ const defaultCategoryId =
175+ modalCategories ?. data ?. categories ?. [ 0 ] ?. categoryId ?? null ;
176+ const categoryIdToUse = matchId ?? defaultCategoryId ;
177+ const formatTime24 = ( raw : string ) : string => {
178+ const [ period , time ] = raw . split ( ' ' ) ;
179+ const [ hourStr , minuteStr ] = time . split ( ':' ) ;
180+ let hour = Number ( hourStr ) ;
181+ const minute = Number ( minuteStr ) ;
182+
183+ if ( period === '오후' && hour !== 12 ) {
184+ hour += 12 ;
185+ }
186+ if ( period === '오전' && hour === 12 ) {
187+ hour = 0 ;
188+ }
189+
190+ return `${ String ( hour ) . padStart ( 2 , '0' ) } :${ String ( minute ) . padStart ( 2 , '0' ) } ` ;
191+ } ;
192+
193+ const formattedTime = formatTime24 ( formState . time ) ;
194+ const formattedDate = formState . date . replace ( / \. / g, '-' ) ;
195+ const remindTime = `${ formattedDate } T${ formattedTime } :00` ;
196+ const remindTimeFormatted = remindTime ;
197+
198+ patchArticle (
199+ {
200+ articleId : articleId ,
201+ categoryId : categoryIdToUse ,
202+ memo : memo ,
203+ remindTime : remindTimeFormatted ,
204+ } ,
205+ {
206+ onSuccess : ( data ) => {
207+ console . log ( '✅ 저장 성공:' , data ) ;
208+ // window.close(); // 최종 배포 시 주석 해제
209+ } ,
210+ onError : ( error : any ) => {
211+ const message = error ?. response ?. data ?. message ;
212+ alert ( '❌ 저장 실패:' + message ) ;
213+ } ,
214+ }
215+ ) ;
216+ } ;
217+
96218 useEffect ( ( ) => {
97219 if ( modalCategories ) {
98220 const categoryNames : string [ ] = modalCategories . data . categories . map (
@@ -126,14 +248,18 @@ const ModalPop = ({ onClose, onDelete, selectedArticleId }: ModalPopProps) => {
126248 time : formattedTime ,
127249 } ) ) ;
128250 const og = await fetchOGData ( articleDetail . url ) ;
251+ const actualUrl = articleDetail ?. url ?? '' ;
252+ const actualArticeId = articleDetail ?. articleId ?? '' ;
253+ setArticleId ( actualArticeId ) ;
254+ setUrl ( actualUrl || '' ) ;
129255 setTitle ( og . title || '' ) ;
130256 setDescription ( og . siteName || '' ) ;
131257 setImage ( og . image || '' ) ;
132258 }
133259 } ;
134260
135261 test ( ) ;
136- } , [ articleDetail ] ) ;
262+ } , [ articleDetail , url ] ) ;
137263
138264 return (
139265 < div className = "relative flex h-[64.2rem] w-[38.7rem] flex-col items-center justify-between rounded-[1rem] bg-white px-[3rem] py-[3rem]" >
@@ -158,8 +284,10 @@ const ModalPop = ({ onClose, onDelete, selectedArticleId }: ModalPopProps) => {
158284 < TextArea
159285 defaultValue = { articleDetail ?. memo }
160286 size = "large"
287+ value = { memo }
161288 maxLength = { POP_TEXTAREA_MAX_LENGTH }
162289 placeholder = "메모를 입력하고 도토리를 받아보세요!"
290+ onChange = { ( e ) => setMemo ( e . target . value ) }
163291 />
164292 </ section >
165293 < section >
@@ -202,25 +330,22 @@ const ModalPop = ({ onClose, onDelete, selectedArticleId }: ModalPopProps) => {
202330 text = "저장하기"
203331 size = "medium"
204332 type = "green"
205- onClick = { onClose }
333+ onClick = { ( ) => {
334+ handleSave ( ) ;
335+ onClose ( ) ;
336+ } }
206337 />
207338 </ div >
208- { /* TODO : 하드코딩 데이터 구간 */ }
209339
210340 { categoryPopupMode && (
211341 < TextFieldPopup
212342 mode = { categoryPopupMode }
213343 value = { categoryPopupMode === 'edit' ? selectedCategory : '' }
214344 existingCategories = { categories }
215345 onCancel = { handlePopupClose }
346+ onEdit = { handlePopupEdit }
216347 onConfirm = { handlePopupConfirm }
217- onDelete = { ( ) => {
218- setCategories ( ( prev ) =>
219- prev . filter ( ( cat ) => cat !== selectedCategory )
220- ) ;
221- setSelectedCategory ( '' ) ;
222- handlePopupClose ( ) ;
223- } }
348+ onDelete = { handlePopupDelete }
224349 />
225350 ) }
226351 </ div >
0 commit comments