import React, { useState } from 'react'; import { Card } from '../ui/card'; import { Button } from '../ui/button'; import { Check, ChevronRight, Layers } from 'lucide-react'; import { useToast } from '../../context/ToastContext'; import { FileUploadZone } from '../upload/FileUploadZone'; import { FilePreviewCard, UploadFile } from '../upload/FilePreviewCard'; import { BulkUploadModal } from '../upload/BulkUploadModal'; import { MetadataEditor } from '../upload/metadata/MetadataEditor'; import { uploadService } from '../../services/uploadService'; export const UploadView: React.FC = () => { const { addToast } = useToast(); const [step, setStep] = useState(1); // File State const [files, setFiles] = useState([]); const [showBulkModal, setShowBulkModal] = useState(false); // --- STEP 1 LOGIC: UPLOAD HANDLING --- const handleFilesSelected = (newFiles: File[]) => { const uploadFiles: UploadFile[] = newFiles.map((f) => ({ id: Math.random().toString(36).substr(2, 9), file: f, progress: 0, status: 'paused', previewUrl: f.type.startsWith('image/') ? URL.createObjectURL(f) : undefined, })); setFiles((prev) => [...prev, ...uploadFiles]); if (uploadFiles.length > 1 || files.length > 0) { // Optional: Auto open bulk modal if many files // setShowBulkModal(true); } addToast(`${newFiles.length} files selected`, 'info'); // Auto-start upload uploadFiles.forEach((uf) => triggerUpload(uf)); }; const triggerUpload = async (uploadFile: UploadFile) => { setFiles((prev) => prev.map((f) => f.id === uploadFile.id ? { ...f, status: 'uploading' } : f, ), ); try { // Using the new chunked upload from uploadService // Here we provide basic metadata from the filename const metadata = { title: uploadFile.file.name.split('.').slice(0, -1).join('.') || uploadFile.file.name, artist: 'Unknown Artist', // Placeholder, would be updated in Step 2 genre: 'None', }; await uploadService.uploadTrack(uploadFile.file, metadata, (progress) => { setFiles((prev) => { // Check if cancelled/paused const current = prev.find((f) => f.id === uploadFile.id); if ( !current || current.status === 'paused' || current.status === 'error' ) return prev; return prev.map((f) => f.id === uploadFile.id ? { ...f, progress } : f, ); }); }); setFiles((prev) => prev.map((f) => f.id === uploadFile.id ? { ...f, progress: 100, status: 'completed' } : f, ), ); } catch (error) { setFiles((prev) => prev.map((f) => f.id === uploadFile.id ? { ...f, status: 'error' } : f, ), ); addToast(`Failed to upload ${uploadFile.file.name}`, 'error'); } }; const handlePause = (id: string) => { // In real app, abort controller would be used setFiles((prev) => prev.map((f) => (f.id === id ? { ...f, status: 'paused' } : f)), ); }; const handleResume = (id: string) => { const file = files.find((f) => f.id === id); if (file) triggerUpload(file); }; const handleCancel = (id: string) => { setFiles((prev) => prev.filter((f) => f.id !== id)); }; const handleStartBulkUpload = () => { files .filter((f) => f.status !== 'completed' && f.status !== 'uploading') .forEach((f) => triggerUpload(f)); }; const allCompleted = files.length > 0 && files.every((f) => f.status === 'completed'); const handleMetadataComplete = (_metadata: any) => { // Here we would sync metadata with backend for the uploaded files // await trackService.updateMetadata(metadata); setStep(3); }; // --- RENDER --- return (

UPLOAD STUDIO

Publish your sounds to the Veza Network.

{/* Stepper */}
{[ { num: 1, label: 'Upload' }, { num: 2, label: 'Metadata' }, { num: 3, label: 'Review' }, { num: 4, label: 'Publish' }, ].map((s, i) => (
= s.num ? 'bg-kodo-cyan text-black' : 'bg-kodo-slate text-gray-500'}`} > {step > s.num ? : s.num}
= s.num ? 'text-white' : 'text-gray-600'} font-medium hidden md:block`} > {s.label} {i < 3 && (
)}
))}
{/* STEP 1: UPLOAD CORE */} {step === 1 && (
{files.length === 0 ? (
) : (

Files ({files.length})

{ if (e.target.files) handleFilesSelected(Array.from(e.target.files)); }} />
{files.map((file) => ( handlePause(file.id)} onResume={() => handleResume(file.id)} onCancel={() => handleCancel(file.id)} /> ))}
{allCompleted ? ( All files uploaded successfully ) : ( Processing uploads... please wait. )}
)}
)} {/* STEP 2: METADATA EDITOR */} {step === 2 && (
setStep(1)} onNext={handleMetadataComplete} />
)} {/* STEP 3: SUCCESS PLACEHOLDER */} {step >= 3 && (

Ready to Publish

Your tracks have been metadata tagged and are ready for distribution on the Veza Network.

)}
{/* MODALS */} {showBulkModal && ( setShowBulkModal(false)} onStartUpload={handleStartBulkUpload} onCancelFile={handleCancel} onPauseFile={handlePause} onResumeFile={handleResume} /> )}
); };