fromis_9/frontend-temp/src/components/pc/admin/album/PhotoPreviewModal.jsx
caadiq cf8cdb7ec6 refactor: AlbumPhotos.jsx 분리 - 4개 컴포넌트 추출
- PendingFileItem.jsx 추출 (업로드 대기 파일 아이템)
- BulkEditPanel.jsx 추출 (일괄 편집 도구 + parseRange 함수)
- PhotoGrid.jsx 추출 (컨셉 포토/티저 그리드)
- PhotoPreviewModal.jsx 추출 (이미지/비디오 미리보기)
- AlbumPhotos.jsx: 1536줄 → 1033줄 (503줄 감소)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 23:46:52 +09:00

58 lines
1.8 KiB
JavaScript

/**
* 사진/비디오 미리보기 모달 컴포넌트
*/
import { memo } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import { X } from 'lucide-react';
/**
* @param {Object} props
* @param {Object|null} props.photo - 미리보기할 사진/비디오 객체
* @param {Function} props.onClose - 닫기 핸들러
*/
const PhotoPreviewModal = memo(function PhotoPreviewModal({ photo, onClose }) {
return (
<AnimatePresence>
{photo && (
<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
className="fixed inset-0 z-50 flex items-center justify-center bg-black/90"
onClick={onClose}
>
<button
onClick={onClose}
className="absolute top-4 right-4 p-2 text-white/70 hover:text-white transition-colors"
>
<X size={24} />
</button>
{photo.isVideo ? (
<motion.video
initial={{ scale: 0.9 }}
animate={{ scale: 1 }}
exit={{ scale: 0.9 }}
src={photo.preview || photo.url}
className="max-w-[90vw] max-h-[90vh] object-contain"
onClick={(e) => e.stopPropagation()}
controls
autoPlay
/>
) : (
<motion.img
initial={{ scale: 0.9 }}
animate={{ scale: 1 }}
exit={{ scale: 0.9 }}
src={photo.preview || photo.url}
alt={photo.filename}
className="max-w-[90vw] max-h-[90vh] object-contain"
onClick={(e) => e.stopPropagation()}
/>
)}
</motion.div>
)}
</AnimatePresence>
);
});
export default PhotoPreviewModal;