import React from 'react'; import { Film, Volume2, Monitor, Square, Smartphone } from 'lucide-react'; import { DesignMD } from '../../../types'; interface PreviewTimelineProps { designMD: DesignMD; aspectRatio?: '16:9' | '1:1' | '9:16'; } const RATIO_INFO: Record = { '16:9': { icon: , res: '1920×1080', label: 'Landscape' }, '1:1': { icon: , res: '1080×1080', label: 'Cuadrado' }, '9:16': { icon: , res: '1080×1920', label: 'Vertical' }, }; /** * Visual timeline mockup showing the video structure: * intro → transition → content → transition → outro + audio status. */ export const PreviewTimeline: React.FC = ({ designMD, aspectRatio = '9:16' }) => { const hasIntro = !!designMD.introVideoUrl; const hasOutro = !!designMD.outroVideoUrl; const hasAudio = !!designMD.brandAudioUrl; const introDur = designMD.introDurationFrames || 60; const outroDur = designMD.outroDurationFrames || 60; const totalDur = (hasIntro ? introDur : 0) + (hasOutro ? outroDur : 0) || 1; return (
{/* Timeline Blocks */}

Estructura del Video

{RATIO_INFO[aspectRatio]?.icon} {aspectRatio} · {RATIO_INFO[aspectRatio]?.res}
{/* Timeline visual */}
{/* Intro */} {hasIntro && ( } duration={introDur} color={designMD.primaryColor} widthPercent={(introDur / totalDur) * 100} /> )} {/* Outro */} {hasOutro && ( } duration={outroDur} color={designMD.primaryColor} widthPercent={(outroDur / totalDur) * 100} /> )}
{/* Duration */}
0:00 {(totalDur / 30).toFixed(1)}s · {RATIO_INFO[aspectRatio]?.label} · 30fps
{/* Audio Status */}

Audio de Marca

{hasAudio ? (
{/* Audio waveform mockup */}
{Array.from({ length: 32 }).map((_, i) => (
))}

{designMD.brandAudioUrl?.split('/').pop() || 'audio.mp3'}

{Math.round((designMD.brandAudioVolume ?? 0.8) * 100)}%
{/* Fade indicators */}
{designMD.autoFadeInAudio && ( ↗ Fade-In {((designMD.audioFadeInDuration || 15) / 30).toFixed(1)}s )} {designMD.autoFadeOutAudio && ( ↘ Fade-Out {((designMD.audioFadeOutDuration || 15) / 30).toFixed(1)}s )} {!designMD.autoFadeInAudio && !designMD.autoFadeOutAudio && ( Sin fade automático )}
) : (

Sin audio de marca configurado

)}
); }; // ─── Sub-components ─── const TimelineBlock: React.FC<{ label: string; icon: React.ReactNode; duration: number; color: string; widthPercent: number; isMain?: boolean; }> = ({ label, icon, duration, color, widthPercent, isMain }) => (
{icon} {label} {(duration / 30).toFixed(1)}s
); function getWaveformOpacity(i: number, total: number, designMD: DesignMD): number { let opacity = 1; const fadeInFrames = designMD.audioFadeInDuration || 15; const fadeOutFrames = designMD.audioFadeOutDuration || 15; const fadeInBars = Math.ceil((fadeInFrames / 300) * total); const fadeOutBars = Math.ceil((fadeOutFrames / 300) * total); if (designMD.autoFadeInAudio && i < fadeInBars) { opacity = i / fadeInBars; } if (designMD.autoFadeOutAudio && i > total - fadeOutBars) { opacity = (total - i) / fadeOutBars; } return Math.max(0.1, opacity); }