'use client'; import { useState, useCallback } from 'react'; import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { Download, X, Loader2 } from 'lucide-react'; import { cn } from '@/lib/utils'; interface ExportModalProps { durationBars: number; bpm: number; onExport: () => Promise; onClose: () => void; className?: string; } export function ExportModal({ durationBars, bpm, onExport, onClose, className, }: ExportModalProps) { const [filename, setFilename] = useState('lofi-beat'); const [isExporting, setIsExporting] = useState(false); const [progress, setProgress] = useState(0); const [error, setError] = useState(null); const secondsPerBar = (60 / bpm) * 4; const totalSeconds = durationBars * secondsPerBar; const estimatedSizeKB = Math.round(totalSeconds * 44.1 * 2 * 2); const estimatedSizeMB = (estimatedSizeKB / 1024).toFixed(1); const formatDuration = (seconds: number) => { const mins = Math.floor(seconds / 60); const secs = Math.floor(seconds % 60); return `${mins}:${secs.toString().padStart(2, '0')}`; }; const handleExport = useCallback(async () => { setIsExporting(true); setError(null); setProgress(0); const progressInterval = setInterval(() => { setProgress((p) => Math.min(p + Math.random() * 10, 90)); }, 200); try { const blob = await onExport(); setProgress(100); const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = `${filename}.wav`; document.body.appendChild(a); a.click(); document.body.removeChild(a); URL.revokeObjectURL(url); setTimeout(onClose, 500); } catch (err) { setError(err instanceof Error ? err.message : 'Export failed'); } finally { clearInterval(progressInterval); setIsExporting(false); } }, [filename, onExport, onClose]); return (
Export Audio
setFilename(e.target.value)} className={cn( 'flex-1 px-3 py-2 text-sm rounded-md bg-muted border border-border', 'focus:outline-none focus:ring-2 focus:ring-primary' )} /> .wav
Duration: {formatDuration(totalSeconds)}
Size: ~{estimatedSizeMB} MB
Format: WAV 44.1kHz 16-bit
Bars: {durationBars}
{isExporting && (
Rendering... {Math.round(progress)}%
)} {error && (
{error}
)}
); }