Add upload capability to AssetLibrary modal

- Added Upload button to asset selection modal
- Users can now upload files directly when selecting images
- Works for Veo first/last frames, reference images, etc.
- Auto-selects uploaded file in single-select mode
- Shows upload progress indicator

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
DJP 2025-12-09 20:55:14 -05:00
parent 4b096f45cb
commit 321dec4029

View file

@ -1,8 +1,9 @@
'use client';
import { useState, useEffect } from 'react';
import api from '@/lib/api';
import api, { assetsApi } from '@/lib/api';
import { clsx } from 'clsx';
import { toast } from 'react-hot-toast';
import {
X,
Search,
@ -13,7 +14,9 @@ import {
Check,
Loader2,
FolderOpen,
Upload,
} from 'lucide-react';
import FileUpload from './FileUpload';
interface Asset {
id: string;
@ -59,6 +62,8 @@ export default function AssetLibrary({
const [page, setPage] = useState(1);
const [totalPages, setTotalPages] = useState(1);
const [selectedAssets, setSelectedAssets] = useState<Set<string>>(new Set());
const [showUpload, setShowUpload] = useState(false);
const [uploading, setUploading] = useState(false);
useEffect(() => {
if (isOpen) {
@ -108,6 +113,25 @@ export default function AssetLibrary({
onClose();
};
const handleUpload = async (file: File) => {
setUploading(true);
try {
const response = await assetsApi.upload(file);
toast.success('File uploaded!');
loadAssets(); // Reload to show new file
// Auto-select the new file
if (!multiple) {
onSelect(response.data);
setShowUpload(false);
onClose();
}
} catch (error) {
toast.error('Failed to upload file');
} finally {
setUploading(false);
}
};
if (!isOpen) return null;
return (
@ -119,12 +143,21 @@ export default function AssetLibrary({
<FolderOpen className="w-5 h-5 text-forge-yellow" />
<h2 className="text-lg font-semibold text-white">{title}</h2>
</div>
<button
onClick={onClose}
className="p-2 text-gray-400 hover:text-white transition-colors"
>
<X className="w-5 h-5" />
</button>
<div className="flex items-center gap-2">
<button
onClick={() => setShowUpload(!showUpload)}
className="px-3 py-2 bg-forge-yellow/10 text-forge-yellow rounded-lg hover:bg-forge-yellow/20 transition-colors flex items-center gap-2 text-sm"
>
<Upload className="w-4 h-4" />
Upload New
</button>
<button
onClick={onClose}
className="p-2 text-gray-400 hover:text-white transition-colors"
>
<X className="w-5 h-5" />
</button>
</div>
</div>
{/* Filters */}
@ -184,6 +217,29 @@ export default function AssetLibrary({
</div>
</div>
{/* Upload Section */}
{showUpload && (
<div className="p-4 border-b border-gray-800">
<FileUpload
onUpload={handleUpload}
accept={
fileTypes.includes('image')
? { 'image/*': ['.png', '.jpg', '.jpeg', '.webp', '.gif'] }
: fileTypes.includes('video')
? { 'video/*': ['.mp4', '.webm', '.mov'] }
: { 'audio/*': ['.mp3', '.wav', '.ogg'] }
}
label="Drop file here or click to upload"
/>
{uploading && (
<div className="mt-2 flex items-center gap-2 text-forge-yellow text-sm">
<Loader2 className="w-4 h-4 animate-spin" />
Uploading...
</div>
)}
</div>
)}
{/* Asset Grid */}
<div className="flex-1 overflow-y-auto p-4">
{loading ? (