'use client' import { useState, useEffect } from 'react' import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card' import { Button } from '@/components/ui/button' import { Input } from '@/components/ui/input' import { Label } from '@/components/ui/label' import { Badge } from '@/components/ui/badge' import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs' import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select' import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog' import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger } from '@/components/ui/alert-dialog' import { Checkbox } from '@/components/ui/checkbox' import { useToast } from '@/hooks/use-toast' import { useFileUpload } from '@/hooks/use-file-upload' import { LoadingSpinner } from './loading-states' import { ErrorBoundary } from './error-boundary' import { Upload, Search, Filter, Grid, List, Eye, Edit, Trash2, Download, Folder, File, Image as ImageIcon, FileText, Video, Music, Archive, Plus, X, FolderPlus, Move, Copy, MoreHorizontal, Calendar, HardDrive, BarChart3 } from 'lucide-react' import Image from 'next/image' import { FileUpload } from '@/types/database' interface FileNode { id: string name: string type: 'file' | 'folder' size?: number mimeType?: string url?: string createdAt: Date children?: FileNode[] path: string } interface FileStats { totalFiles: number totalSize: string recentUploads: number storageUsed: string fileTypes: { [key: string]: number } } export function FileManager() { const [files, setFiles] = useState([]) const [stats, setStats] = useState(null) const [loading, setLoading] = useState(true) const [viewMode, setViewMode] = useState<'grid' | 'list' | 'tree'>('grid') const [searchTerm, setSearchTerm] = useState('') const [selectedFiles, setSelectedFiles] = useState>(new Set()) const [currentPath, setCurrentPath] = useState('/') const [showUploadDialog, setShowUploadDialog] = useState(false) const [showNewFolderDialog, setShowNewFolderDialog] = useState(false) const [newFolderName, setNewFolderName] = useState('') const { toast } = useToast() const { uploadFiles, isUploading, progress } = useFileUpload({ maxFiles: 50, maxSize: 10 * 1024 * 1024, // 10MB allowedTypes: ['image/*', 'video/*', 'audio/*', 'application/pdf', 'text/*'], }) useEffect(() => { loadFiles() loadStats() }, [currentPath]) const loadFiles = async () => { try { const response = await fetch(`/api/files?path=${encodeURIComponent(currentPath)}`) if (!response.ok) throw new Error('Failed to load files') const data = await response.json() setFiles(data) } catch (error) { toast({ title: 'Error', description: 'Failed to load files', variant: 'destructive', }) } } const loadStats = async () => { try { const response = await fetch('/api/files/stats') if (!response.ok) throw new Error('Failed to load stats') const data = await response.json() setStats(data) } catch (error) { console.error('Failed to load stats:', error) } finally { setLoading(false) } } const handleFileUpload = async (files: FileList) => { try { const fileArray = Array.from(files) await uploadFiles(fileArray, { keyPrefix: currentPath.replace('/', '') }) await loadFiles() await loadStats() setShowUploadDialog(false) toast({ title: 'Success', description: `Uploaded ${fileArray.length} files successfully`, }) } catch (error) { toast({ title: 'Error', description: 'Failed to upload files', variant: 'destructive', }) } } const handleCreateFolder = async () => { if (!newFolderName.trim()) return try { const response = await fetch('/api/files/folder', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: newFolderName, path: currentPath }), }) if (!response.ok) throw new Error('Failed to create folder') await loadFiles() setShowNewFolderDialog(false) setNewFolderName('') toast({ title: 'Success', description: 'Folder created successfully', }) } catch (error) { toast({ title: 'Error', description: 'Failed to create folder', variant: 'destructive', }) } } const handleDeleteFiles = async () => { try { const response = await fetch('/api/files/bulk-delete', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ fileIds: Array.from(selectedFiles) }), }) if (!response.ok) throw new Error('Failed to delete files') await loadFiles() await loadStats() setSelectedFiles(new Set()) toast({ title: 'Success', description: `Deleted ${selectedFiles.size} items successfully`, }) } catch (error) { toast({ title: 'Error', description: 'Failed to delete files', variant: 'destructive', }) } } const toggleFileSelection = (fileId: string) => { const newSelection = new Set(selectedFiles) if (newSelection.has(fileId)) { newSelection.delete(fileId) } else { newSelection.add(fileId) } setSelectedFiles(newSelection) } const getFileIcon = (file: FileNode) => { if (file.type === 'folder') return if (file.mimeType?.startsWith('image/')) return if (file.mimeType?.startsWith('video/')) return