@@ -203,27 +203,101 @@ export const signIn = async (email: string, password: string) => {
203203 return response . json ( ) ;
204204} ;
205205
206- export const addArticle = async (
207- title : string ,
208- content : string ,
209- image ?: string
210- ) : Promise < void > => {
206+ export const refreshAccessToken = async ( ) : Promise < string > => {
207+ const refreshToken = localStorage . getItem ( "refreshToken" ) ;
208+ if ( ! refreshToken ) {
209+ throw new Error ( "리프레시 토큰이 없습니다. 다시 로그인해주세요." ) ;
210+ }
211+
212+ const response = await fetch ( `${ BASE_URL } auth/refresh-token` , {
213+ method : "POST" ,
214+ headers : {
215+ "Content-Type" : "application/json" ,
216+ } ,
217+ body : JSON . stringify ( { refreshToken } ) ,
218+ } ) ;
219+
220+ if ( ! response . ok ) {
221+ const errorData = await response . json ( ) ;
222+ throw new Error ( errorData . message || "토큰 갱신 실패" ) ;
223+ }
224+
225+ const data = await response . json ( ) ;
226+ localStorage . setItem ( "accessToken" , data . accessToken ) ;
227+ return data . accessToken ;
228+ } ;
229+
230+ export const uploadImage = async ( image : File ) : Promise < string > => {
211231 const token = localStorage . getItem ( "accessToken" ) ;
212232 if ( ! token ) {
213233 throw new Error ( "로그인이 필요합니다." ) ;
214234 }
215235
216- const response = await fetch ( `${ BASE_URL } articles` , {
236+ const formData = new FormData ( ) ;
237+ formData . append ( "file" , image ) ;
238+
239+ const response = await fetch ( `${ BASE_URL } images/upload` , {
217240 method : "POST" ,
218241 headers : {
219- "Content-Type" : "application/json" ,
220242 Authorization : `Bearer ${ token } ` ,
221243 } ,
222- body : JSON . stringify ( { title , content , image } ) ,
244+ body : formData ,
223245 } ) ;
224246
225247 if ( ! response . ok ) {
226248 const errorData = await response . json ( ) ;
227- throw new Error ( errorData . message || "게시물 등록 실패" ) ;
249+ throw new Error ( errorData . message || "이미지 업로드 실패" ) ;
250+ }
251+
252+ const data = await response . json ( ) ;
253+ return data . url ;
254+ } ;
255+
256+ export const addArticle = async (
257+ title : string ,
258+ content : string ,
259+ image ?: File | null
260+ ) : Promise < void > => {
261+ let token = localStorage . getItem ( "accessToken" ) ;
262+ if ( ! token ) {
263+ throw new Error ( "로그인이 필요합니다." ) ;
264+ }
265+
266+ try {
267+ const body = { title, content } ;
268+
269+ const response = await fetch ( `${ BASE_URL } articles` , {
270+ method : "POST" ,
271+ headers : {
272+ "Content-Type" : "application/json" ,
273+ Authorization : `Bearer ${ token } ` ,
274+ } ,
275+ body : JSON . stringify ( body ) ,
276+ } ) ;
277+
278+ if ( ! response . ok ) {
279+ if ( response . status === 401 ) {
280+ const newToken = await refreshAccessToken ( ) ;
281+ token = newToken ;
282+
283+ const retryResponse = await fetch ( `${ BASE_URL } articles` , {
284+ method : "POST" ,
285+ headers : {
286+ "Content-Type" : "application/json" ,
287+ Authorization : `Bearer ${ token } ` ,
288+ } ,
289+ body : JSON . stringify ( body ) ,
290+ } ) ;
291+
292+ if ( ! retryResponse . ok ) {
293+ throw new Error ( "게시물 등록 실패" ) ;
294+ }
295+ } else {
296+ const errorData = await response . json ( ) ;
297+ throw new Error ( errorData . message || "게시물 등록 실패" ) ;
298+ }
299+ }
300+ } catch ( error ) {
301+ throw new Error ( error instanceof Error ? error . message : "오류 발생" ) ;
228302 }
229303} ;
0 commit comments