import React, { useRef, useState, useEffect } from 'react'; import { useTranslation } from 'react-i18next'; import { ImageItem, ImageUrlItem } from '../../types/api'; import { uploadImages } from '../../utils/api'; interface AssetManagementContentProps { onNext: (imageTaskId: string) => void; onBack?: () => void; imageList: ImageItem[]; onRemoveImage: (index: number) => void; onAddImages: (files: File[]) => void; } type VideoRatio = 'vertical' | 'horizontal'; const IMAGES_PER_PAGE = 12; const AssetManagementContent: React.FC = ({ onNext, onBack, imageList, onRemoveImage, onAddImages, }) => { const { t } = useTranslation(); const fileInputRef = useRef(null); const [isUploading, setIsUploading] = useState(false); const [uploadProgress, setUploadProgress] = useState(0); const [uploadError, setUploadError] = useState(null); const [videoRatio, setVideoRatio] = useState('vertical'); const [displayCount, setDisplayCount] = useState(IMAGES_PER_PAGE); useEffect(() => { const savedRatio = localStorage.getItem('castad_video_ratio') as VideoRatio; if (savedRatio === 'vertical' || savedRatio === 'horizontal') { setVideoRatio(savedRatio); } }, []); const handleVideoRatioChange = (ratio: VideoRatio) => { setVideoRatio(ratio); localStorage.setItem('castad_video_ratio', ratio); }; const getImageSrc = (item: ImageItem): string => { return item.type === 'url' ? item.preview_url : item.preview; }; const handleNextWithUpload = async () => { if (imageList.length === 0) return; setIsUploading(true); setUploadProgress(0); setUploadError(null); const interval = setInterval(() => { setUploadProgress(prev => { if (prev >= 99) return prev; return prev + (prev < 50 ? 0.6 : prev < 80 ? 0.3 : prev < 90 ? 0.15 : 0.11); }); }, 200); try { const urlImages: ImageUrlItem[] = imageList .filter((item: ImageItem): item is ImageItem & { type: 'url' } => item.type === 'url') .map((item) => ({ url: item.url })); const fileImages: File[] = imageList .filter((item: ImageItem): item is ImageItem & { type: 'file' } => item.type === 'file') .map((item) => item.file); if (urlImages.length > 0 || fileImages.length > 0) { const response = await uploadImages(urlImages, fileImages); clearInterval(interval); setUploadProgress(100); // 이미지 변경 시 이전 음악/영상 생성 결과 초기화 — 반드시 재생성하도록 강제 localStorage.removeItem('castad_song_generation'); localStorage.removeItem('castad_song_completion'); localStorage.removeItem('castad_song_task_id'); localStorage.removeItem('castad_video_generation'); localStorage.removeItem('castad_video_complete'); onNext(response.task_id); } } catch (error) { clearInterval(interval); console.error('Image upload failed:', error); setUploadError(error instanceof Error ? error.message : t('assetManagement.uploadFailed')); } finally { setIsUploading(false); setUploadProgress(0); } }; const handleDragOver = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); }; const handleDrop = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); const files = Array.from(e.dataTransfer.files).filter((file: File) => file.type.startsWith('image/') ); if (files.length > 0) onAddImages(files); }; const handleFileSelect = () => { fileInputRef.current?.click(); }; const handleFileChange = (e: React.ChangeEvent) => { const files = e.target.files; if (files && files.length > 0) { onAddImages(Array.from(files)); e.target.value = ''; } }; const visibleImages = imageList.slice(0, displayCount); const hasMore = imageList.length > displayCount; return (
{isUploading && (

{t('assetManagement.uploading')}

{Math.floor(uploadProgress)}%
)} {/* Fixed Header - 뒤로가기 버튼 */}
{onBack && ( )}
{/* Single Scrollable Content Area */}

{t('assetManagement.title')}

{/* Left Column - Selected Images */}

{t('assetManagement.selectedImages')}

{t('assetManagement.minImages')}
{visibleImages.length > 0 && (
{visibleImages.map((item, i) => (
{`${t('assetManagement.imageAlt')} {item.type === 'file' && (
{t('assetManagement.uploadBadge')}
)}
))}
)}
{hasMore && ( )}
{/* Right Column - Upload and Video Ratio */}
{/* Image Upload Section (desktop only) */}

{t('assetManagement.imageUpload')}

{t('assetManagement.dragAndDrop').split('\n').map((line, i) => ( {i > 0 &&
}{line}
))}

{/* Video Ratio Section */}

{t('assetManagement.videoRatio')}

{/* Fixed Footer - 다음 단계 버튼 */}
{uploadError && (

{uploadError}

)}
); }; export default AssetManagementContent;