"use client"; import React, { useState, useCallback, useEffect } from "react"; import { Button } from "@/components/ui/Button"; import { Input } from "@/components/ui/Input"; import { Card } from "@/components/ui/Card"; import { Modal } from "@/components/ui/Modal"; interface MediaFile { id: string; fileName: string; originalName: string; mimeType: string; size: number; url: string; cdnUrl?: string; thumbnailUrl?: string; createdAt: string; tags: string[]; description?: string; dimensions?: { width: number; height: number; }; } interface MediaPickerProps { isOpen: boolean; onClose: () => void; onSelect: (media: MediaFile | MediaFile[]) => void; multiSelect?: boolean; acceptedTypes?: string[]; maxFiles?: number; className?: string; } export function MediaPicker({ isOpen, onClose, onSelect, multiSelect = false, acceptedTypes = ["image/*", "video/*"], maxFiles = 1, className, }: MediaPickerProps) { const [activeTab, setActiveTab] = useState("library"); const [searchTerm, setSearchTerm] = useState(""); const [selectedFiles, setSelectedFiles] = useState([]); const [mediaFiles, setMediaFiles] = useState([]); const [loading, setLoading] = useState(false); // 미디어 파일 불러오기 const fetchMediaFiles = useCallback(async () => { setLoading(true); try { const response = await fetch("/api/media/upload", { method: "GET", }); if (response.ok) { const data = await response.json(); setMediaFiles(data.files || []); } } catch (error) { console.error("Failed to fetch media files:", error); } finally { setLoading(false); } }, []); useEffect(() => { if (isOpen) { fetchMediaFiles(); } }, [isOpen, fetchMediaFiles]); // 파일 필터링 const filteredFiles = mediaFiles.filter((file) => { const matchesSearch = file.originalName .toLowerCase() .includes(searchTerm.toLowerCase()); return matchesSearch; }); // 파일 선택 처리 const handleFileSelect = useCallback( (file: MediaFile) => { if (multiSelect) { setSelectedFiles((prev) => { const isSelected = prev.some((f) => f.id === file.id); if (isSelected) { return prev.filter((f) => f.id !== file.id); } else if (prev.length < maxFiles) { return [...prev, file]; } return prev; }); } else { setSelectedFiles([file]); } }, [multiSelect, maxFiles] ); // 선택 확인 const handleConfirmSelection = () => { if (selectedFiles.length > 0) { onSelect(multiSelect ? selectedFiles : selectedFiles[0]); setSelectedFiles([]); onClose(); } }; return (

미디어 선택

{/* 탭 버튼 */}
{activeTab === "library" && (
{/* 검색 */}
setSearchTerm(e.target.value)} />
{/* 미디어 파일 그리드 */}
{loading ? (
로딩 중...
) : (
{filteredFiles.map((file) => { const isSelected = selectedFiles.some( (f) => f.id === file.id ); return ( handleFileSelect(file)} >
{file.mimeType.startsWith("image/") ? ( {file.originalName} ) : (
파일
)}
{file.originalName}
); })}
)}
)} {activeTab === "upload" && (

파일을 드래그하여 업로드

또는 클릭하여 파일 선택

)} {/* 하단 버튼 */}
{selectedFiles.length > 0 && `${selectedFiles.length}개 파일 선택됨`}
); }