"use client"; import React from 'react'; import { useStore, ReferenceCategory } from '@/lib/store'; import { Clock, Upload, Trash2, CheckCircle, X, Film, Check } from 'lucide-react'; import { cn } from '@/lib/utils'; // FastAPI backend URL - /api in production (nginx proxy), localhost in dev const API_BASE = process.env.NEXT_PUBLIC_API_URL || (typeof window !== 'undefined' && window.location.hostname !== 'localhost' ? '/api' : 'http://localhost:8000'); export function UploadHistory() { const { history, setHistory, selectionMode, setSelectionMode, setCurrentView, settings, videos, addVideo, removeVideo, removeFromHistory, // Multi-select support references, addReference, removeReference, clearReferences } = useStore(); const handleClear = () => { if (confirm("Clear all upload history?")) { setHistory([]); } }; // Check if an item is currently selected as a reference // eslint-disable-next-line @typescript-eslint/no-explicit-any const isSelected = (item: any) => { if (!selectionMode) return false; const categoryRefs = references[selectionMode as ReferenceCategory] || []; const itemId = item.mediaId || item.id; return categoryRefs.some(ref => ref.id === itemId); }; // Toggle selection - add or remove from references // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleToggleSelect = (item: any) => { if (!selectionMode) return; const itemId = item.mediaId || item.id; const ref = { id: itemId, thumbnail: item.url }; if (isSelected(item)) { removeReference(selectionMode as ReferenceCategory, itemId); } else { addReference(selectionMode as ReferenceCategory, ref); } }; // Done - confirm selection and return to gallery const handleDone = () => { setSelectionMode(null); setCurrentView('gallery'); }; const handleCancelSelection = () => { // Clear selections for this category and go back if (selectionMode) { clearReferences(selectionMode as ReferenceCategory); } setSelectionMode(null); setCurrentView('gallery'); }; // Get count of selected items for current category const selectedCount = selectionMode ? (references[selectionMode as ReferenceCategory] || []).length : 0; const [filter, setFilter] = React.useState('all'); const filteredHistory = history.filter(item => { if (filter === 'all') return true; return item.category === filter; }); const [dragActive, setDragActive] = React.useState(false); const handleDrag = (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); if (e.type === "dragenter" || e.type === "dragover") { setDragActive(true); } else if (e.type === "dragleave") { setDragActive(false); } }; const handleDrop = async (e: React.DragEvent) => { e.preventDefault(); e.stopPropagation(); setDragActive(false); if (e.dataTransfer.files && e.dataTransfer.files[0]) { const file = e.dataTransfer.files[0]; if (!file.type.startsWith('image/')) return; // Determine category // 1. If selectionMode is active (e.g. "subject"), use that. // 2. If filter is not 'all', use that. // 3. Default to 'subject'. let category: string = 'subject'; if (selectionMode) category = selectionMode; else if (filter !== 'all') category = filter; // Upload try { const reader = new FileReader(); reader.onload = async (ev) => { const base64 = ev.target?.result as string; if (!base64) return; // Optimistic UI update could happen here const res = await fetch(`${API_BASE}/references/upload`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ imageBase64: base64, mimeType: file.type, category: category, cookies: settings.whiskCookies }) }); const data = await res.json(); if (data.id) { const newItem = { id: data.id, url: base64, category: category, originalName: file.name }; setHistory([newItem, ...history]); // If in selection mode, auto-select it if (selectionMode) { handleToggleSelect(newItem); } } else { alert(`Upload failed: ${data.error}`); } } reader.readAsDataURL(file); } catch (err) { console.error(err); } } }; return (
{/* Selection Mode Header - Sticky */} {selectionMode && (

Select {selectionMode}

{selectedCount > 0 ? `${selectedCount} selected — click photos to add/remove` : 'Click photos to select'}

{selectedCount > 0 && ( )}
)} {!selectionMode && (

Uploads

Your reference collection.

{history.length > 0 && ( )}
)} {/* Filter Tabs */}
{(['all', 'subject', 'scene', 'style', 'videos'] as const).map(cat => ( ))}
{/* Content Area */} {filter === 'videos' ? ( // Video Grid videos.length === 0 ? (

No videos yet

Generate videos from your gallery images using the primary generator.

) : (
{videos.map((vid) => (
))}
) ) : ( // Image/Uploads Grid (Existing Logic) history.length === 0 ? (

No uploads yet

Drag and drop images anywhere or use the plus buttons in the creator.

) : ( <> {filteredHistory.length === 0 ? (
No uploads in this category.
) : (
{filteredHistory.map((item) => { const selected = isSelected(item); return (
{item.originalName} {/* Selection Overlay - Handles Click */}
handleToggleSelect(item)} className="absolute inset-0 z-10 cursor-pointer" role="button" tabIndex={0} onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { handleToggleSelect(item); } }} /> {/* Checkmark for selected items */} {selectionMode && selected && (
)} {/* info overlay (z-20 inside, visual only) */}

{item.originalName}

{item.category}
{/* Delete Button - Isolated on Top (z-50) */} {!selectionMode && ( )}
); })}
)} ) )}
); }