@@ -67,7 +67,13 @@ export default function Feed({ feedData, onFeedClick }) {
6767
6868 useEffect ( ( ) => {
6969 setWorksData ( feedData ) ;
70- setMediaData ( feedData ?. mediaResDtos ) ;
70+ // mediaResDto가 배열인지 단일 객체인지 확인하고 배열로 변환
71+ const mediaArray = Array . isArray ( feedData ?. mediaResDto )
72+ ? feedData . mediaResDto
73+ : feedData ?. mediaResDto
74+ ? [ feedData . mediaResDto ]
75+ : [ ] ;
76+ setMediaData ( mediaArray ) ;
7177 setIsLiked ( feedData ?. liked || false ) ;
7278 setLikedCount ( feedData ?. likedCount || 0 ) ;
7379 } , [ feedData ] ) ;
@@ -91,7 +97,7 @@ export default function Feed({ feedData, onFeedClick }) {
9197 setShowDeleteModal ( false ) ;
9298 setShowCompleteModal ( true ) ;
9399 } catch ( err ) {
94- console . log ( "실패함" , err ) ;
100+ // console.log("실패함" , err);
95101 const errorKey = err ?. response ?. data ?. errorKey ;
96102 if ( err . response ?. status === 403 ) {
97103 setShowLoginModal ( true ) ;
@@ -127,7 +133,7 @@ export default function Feed({ feedData, onFeedClick }) {
127133
128134 const toggleExpand = ( ) => setIsExpanded ( ( prev ) => ! prev ) ;
129135 const handleDeclareClick = ( declareData ) => {
130- console . log ( '신고 데이터:' , declareData ) ;
136+ // console.log('신고 데이터:', declareData);
131137 }
132138
133139 const handleHeartClick = async ( ) => {
@@ -147,7 +153,13 @@ export default function Feed({ feedData, onFeedClick }) {
147153 setWorksData ( updatedData . result ) ;
148154 setIsLiked ( updatedData . result . liked ) ;
149155 setLikedCount ( updatedData . result . likedCount || 0 ) ;
150- setMediaData ( updatedData . result . mediaResDtos ) ;
156+ // mediaResDto가 배열인지 단일 객체인지 확인하고 배열로 변환
157+ const mediaArray = Array . isArray ( updatedData . result ?. mediaResDto )
158+ ? updatedData . result . mediaResDto
159+ : updatedData . result ?. mediaResDto
160+ ? [ updatedData . result . mediaResDto ]
161+ : [ ] ;
162+ setMediaData ( mediaArray ) ;
151163
152164 } catch ( error ) {
153165 console . error ( "피드 관련 에러:" , error ) ;
@@ -228,70 +240,81 @@ export default function Feed({ feedData, onFeedClick }) {
228240 < div
229241 className = "flex justify-center w-full overflow-hidden rounded-md mb-2 relative"
230242 >
231- { feedData ?. mediaResDtos && feedData . mediaResDtos . length > 0 ? (
232- < >
233- < Swiper
234- onSwiper = { ( swiper ) => {
235- swiperRef . current = swiper ;
236- } }
237- pagination = { {
238- dynamicBullets : true ,
239- } }
240- modules = { [ Pagination ] }
241- className = "rounded-lg w-full max-w-[800px]"
242- >
243- { feedData ?. mediaResDtos ?. map ( ( data , i ) => {
244- const isVideo = data . fileType ?. toLowerCase ( ) . startsWith ( "video" ) || data . fileUrl ?. toLowerCase ( ) . endsWith ( ".mp4" ) ;
245- return (
246- < SwiperSlide key = { i } >
247- < div className = "flex justify-center items-center" >
248- { isVideo ? (
249- < video
250- src = { `${ data . fileUrl } ` }
251- controls
252- className = "w-full h-auto max-h-[500px] object-cover cursor-pointer"
253- onClick = { goToDetail }
254- />
255- ) : (
243+ { ( ( ) => {
244+ // mediaResDto가 배열인지 단일 객체인지 확인하고 배열로 변환
245+ const mediaArray = Array . isArray ( feedData ?. mediaResDto )
246+ ? feedData . mediaResDto
247+ : feedData ?. mediaResDto
248+ ? [ feedData . mediaResDto ]
249+ : [ ] ;
250+
251+ if ( mediaArray . length === 0 ) {
252+ return (
253+ < div className = "w-full h-48 bg-gray-100 flex items-center justify-center" >
254+ < p className = "text-gray-400" > 이미지가 없습니다</ p >
255+ </ div >
256+ ) ;
257+ }
258+
259+ return (
260+ < >
261+ < Swiper
262+ onSwiper = { ( swiper ) => {
263+ swiperRef . current = swiper ;
264+ } }
265+ pagination = { {
266+ dynamicBullets : true ,
267+ } }
268+ modules = { [ Pagination ] }
269+ className = "rounded-lg w-full max-w-[800px]"
270+ >
271+ { mediaArray . map ( ( data , i ) => {
272+ // 피드 목록에서는 동영상도 썸네일 이미지(.png)로 표시
273+ // fileUrl이 이미 전체 URL인지 확인 (http:// 또는 https://로 시작하는지)
274+ const isFullUrl = data . fileUrl ?. startsWith ( 'http://' ) || data . fileUrl ?. startsWith ( 'https://' ) ;
275+ const mediaUrl = isFullUrl ? data . fileUrl : `${ BUCKET_URL } ${ data . fileUrl } ` ;
276+
277+ return (
278+ < SwiperSlide key = { i } >
279+ < div className = "flex justify-center items-center" >
256280 < img
257- src = { ` ${ BUCKET_URL } ${ data . fileUrl } ` }
258- alt = { data . fileName }
281+ src = { mediaUrl }
282+ alt = { data . fileName || `미디어 ${ i + 1 } ` }
259283 className = "w-full h-auto max-h-[500px] object-cover aspect-[1/1] cursor-pointer"
260284 onClick = { goToDetail }
285+ onError = { ( e ) => {
286+ e . target . src = basiclogoimg ;
287+ } }
261288 />
262- ) }
263- </ div >
264- </ SwiperSlide >
265- )
266- } ) }
267- </ Swiper >
268- { /* 화살표 버튼 */ }
269- { feedData ?. mediaResDtos && feedData . mediaResDtos . length > 1 && (
270- < div className = "hidden lg:block" >
271- < button
272- onClick = { ( e ) => { e . stopPropagation ( ) ; swiperRef . current ?. slidePrev ( ) ; } }
273- className = "absolute left-2 top-1/2 transform -translate-y-1/2 z-10 w-5 h-5 bg-white/80 rounded-full shadow-lg flex items-center justify-center transition-all duration-200"
274- >
275- < svg className = "w-3 h-3 text-gray-700" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
276- < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M15 19l-7-7 7-7" />
277- </ svg >
278- </ button >
279- < button
280- onClick = { ( e ) => { e . stopPropagation ( ) ; swiperRef . current ?. slideNext ( ) ; } }
281- className = "absolute right-2 top-1/2 transform -translate-y-1/2 z-10 w-5 h-5 bg-white/80 rounded-full shadow-lg flex items-center justify-center transition-all duration-200"
282- >
283- < svg className = "w-3 h-3 text-gray-700" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
284- < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M9 5l7 7-7 7" />
285- </ svg >
286- </ button >
287- </ div >
288- ) }
289- </ >
290- ) : (
291- < div className = "w-full h-48 bg-gray-100 flex items-center justify-center" >
292- < p className = "text-gray-400" > 이미지가 없습니다</ p >
293- </ div >
294- ) }
289+ </ div >
290+ </ SwiperSlide >
291+ ) ;
292+ } ) }
293+ </ Swiper >
294+ { /* 화살표 버튼 */ }
295+ { mediaArray . length > 1 && (
296+ < div className = "hidden lg:block" >
297+ < button
298+ onClick = { ( e ) => { e . stopPropagation ( ) ; swiperRef . current ?. slidePrev ( ) ; } }
299+ className = "absolute left-2 top-1/2 transform -translate-y-1/2 z-10 w-5 h-5 bg-white/80 rounded-full shadow-lg flex items-center justify-center transition-all duration-200"
300+ >
301+ < svg className = "w-3 h-3 text-gray-700" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
302+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M15 19l-7-7 7-7" />
303+ </ svg >
304+ </ button >
305+ < button
306+ onClick = { ( e ) => { e . stopPropagation ( ) ; swiperRef . current ?. slideNext ( ) ; } }
307+ className = "absolute right-2 top-1/2 transform -translate-y-1/2 z-10 w-5 h-5 bg-white/80 rounded-full shadow-lg flex items-center justify-center transition-all duration-200"
308+ >
309+ < svg className = "w-3 h-3 text-gray-700" fill = "none" stroke = "currentColor" viewBox = "0 0 24 24" >
310+ < path strokeLinecap = "round" strokeLinejoin = "round" strokeWidth = { 2 } d = "M9 5l7 7-7 7" />
311+ </ svg >
312+ </ button >
313+ </ div >
314+ ) }
315+ </ >
316+ ) ;
317+ } ) ( ) }
295318 </ div >
296319 </ div >
297320
0 commit comments