import { useState, useRef, useEffect } from 'react' import { useQuery } from '@tanstack/react-query' import { Button } from './ui/button' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from './ui/card' import { Label } from './ui/label' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from './ui/select' import { Upload, X, Check } from 'lucide-react' import { packsApi } from '@/api/packs' interface UploadedImage { id: string file: File preview: string base64: string } interface BulkCardUploadProps { onImagesUploaded: (images: UploadedImage[], packId?: string) => void onClose: () => void } export function BulkCardUpload({ onImagesUploaded, onClose }: BulkCardUploadProps) { const fileInputRef = useRef(null) const [uploadedImages, setUploadedImages] = useState([]) const [isDragging, setIsDragging] = useState(false) const [selectedPackId, setSelectedPackId] = useState('') // Fetch packs for pack selection const { data: packsData } = useQuery({ queryKey: ['packs', 1, 100, ''], queryFn: () => packsApi.getPacks({ page: 1, limit: 100, search: '' }), }) const handleFileSelect = async (files: FileList) => { const newImages: UploadedImage[] = [] for (let i = 0; i < files.length; i++) { const file = files[i] // Validate file type if (!file.type.startsWith('image/')) { continue } // Validate file size (max 5MB) const fileSizeMB = file.size / (1024 * 1024) if (fileSizeMB > 5) { continue } try { const base64 = await fileToBase64(file) const preview = URL.createObjectURL(file) newImages.push({ id: `${Date.now()}-${i}`, file, preview, base64, }) } catch (error) { console.error('Error processing file:', error) } } setUploadedImages((prev) => [...prev, ...newImages]) } const handleInputChange = (e: React.ChangeEvent) => { const files = e.target.files if (files && files.length > 0) { handleFileSelect(files) } // Reset input value to allow selecting the same files again if (fileInputRef.current) { fileInputRef.current.value = '' } } const handleDragOver = (e: React.DragEvent) => { e.preventDefault() e.stopPropagation() setIsDragging(true) } const handleDragLeave = (e: React.DragEvent) => { e.preventDefault() e.stopPropagation() setIsDragging(false) } const handleDrop = (e: React.DragEvent) => { e.preventDefault() e.stopPropagation() setIsDragging(false) const files = e.dataTransfer.files if (files && files.length > 0) { handleFileSelect(files) } } const handleRemove = (id: string) => { setUploadedImages((prev) => { const image = prev.find((img) => img.id === id) if (image) { URL.revokeObjectURL(image.preview) } return prev.filter((img) => img.id !== id) }) } const handleClearAll = () => { uploadedImages.forEach((img) => URL.revokeObjectURL(img.preview)) setUploadedImages([]) } const handleContinue = () => { if (uploadedImages.length > 0) { onImagesUploaded(uploadedImages, selectedPackId || undefined) } } return (

Bulk Card Upload

Upload multiple images, then fill in card details one by one

Upload Images Select multiple image files or drag and drop them here

Selected pack will be applied to all uploaded cards

fileInputRef.current?.click()} >
Click to upload or drag and drop

PNG, JPG, GIF up to 5MB each. Multiple files supported.

{uploadedImages.length > 0 && (
Uploaded Images ({uploadedImages.length}) Review uploaded images and continue to fill in card details
{uploadedImages.map((image) => (
{image.file.name}

{image.file.name}

))}
)} {uploadedImages.length > 0 && (
)}
) } // Helper function to convert file to base64 function fileToBase64(file: File): Promise { return new Promise((resolve, reject) => { const reader = new FileReader() reader.onload = () => { const result = reader.result as string // Remove data:image/...;base64, prefix const base64 = result.split(',')[1] resolve(base64) } reader.onerror = reject reader.readAsDataURL(file) }) }