/** * Plan viewer component for Smart Montage Planner * Displays the generated montage plan with sequences and timeline visualization */ import { Check, Layers, Sparkles, TrendingUp, Wand2, X } from "lucide-react" import { Badge } from "@/components/ui/badge" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Progress } from "@/components/ui/progress" import { ScrollArea, ScrollBar } from "@/components/ui/scroll-area" import { Separator } from "@/components/ui/separator" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { useMediaFiles } from "@/features/app-state/hooks/use-media-files" import type { MediaFile } from "@/features/media/types/media" import { formatTime } from "@/lib/date" import type { MediaItem } from "@/types/generated/tauri-bindings" import { usePlanGenerator } from "../../hooks/use-plan-generator" import { useTimelineIntegration } from "../../hooks/use-timeline-integration" import type { MontagePlan, SequenceType } from "../../types" interface PlanViewerProps { plan: MontagePlan } export function PlanViewer({ plan }: PlanViewerProps) { const { planStats, sequenceBreakdown, emotionalArc, transitionUsage } = usePlanGenerator() const { mediaFiles } = useMediaFiles() const { applyPlanToTimeline, isApplying, error, canApplyPlan } = useTimelineIntegration() // TODO: Implement plan validation const planValidation = null as any const handleApplyToTimeline = async () => { // Convert MediaItem[] to MediaFile[] const convertedMediaFiles: MediaFile[] = mediaFiles.map((item: MediaItem) => ({ id: item.id, path: item.path, name: item.name, isVideo: item.media_type === "Video", isAudio: item.media_type === "Audio", duration: item.duration || 0, format: item.metadata?.format || "", codec: item.metadata?.codec || "", width: item.metadata?.resolution?.width || 0, height: item.metadata?.resolution?.height || 0, frameRate: item.metadata?.frame_rate || 0, bitrate: item.metadata?.bitrate || 0, })) await applyPlanToTimeline(plan, convertedMediaFiles, { createNewSection: true, sectionName: plan.name, applyTransitions: true, }) } const getSequenceColor = (type: SequenceType) => { const colors = { intro: "bg-blue-500", main: "bg-green-500", climax: "bg-red-500", resolution: "bg-purple-500", outro: "bg-indigo-500", montage: "bg-yellow-500", } return colors[type] || "bg-gray-500" } const getScoreColor = (score: number) => { if (score >= 80) return "text-green-600" if (score >= 60) return "text-yellow-600" return "text-red-600" } return (

Montage Plan: {plan.name}

{plan.sequences.length} sequences {formatTime(plan.totalDuration)}
{error && (
{error}
)} {/* Plan Scores */}
Quality Score
{plan.qualityScore.toFixed(0)}%
Engagement Score
{plan.engagementScore.toFixed(0)}%
Coherence Score
{plan.coherenceScore.toFixed(0)}%
{/* Timeline Visualization */} Timeline Preview Visual representation of your montage structure
{plan.sequences.map((sequence) => (
{sequence.type}
{formatTime(sequence.duration)}

{sequence.clips.length} clips

Energy: {sequence.energyLevel}%

))}
{/* Detailed View */} Sequences Rhythm Transitions Validation {/* Sequences Tab */} Sequence Details Breakdown of each sequence in your montage
{sequenceBreakdown.map((seq: any, index: number) => (

{seq.type} #{Number(index || 0) + 1}

{seq.clipCount} clips • {formatTime(seq.duration)}
Energy Level {seq.energyLevel}%
Purpose {seq.purpose.replace("-", " ")}
{index < sequenceBreakdown.length - 1 && }
))}
{/* Rhythm Tab */} Emotional Rhythm Energy flow throughout your montage
{/* Energy Graph */}
{emotionalArc.map((point: any, _index: number) => (
{Math.round(point.peakEnergy)}
))}
Start Peak End
{/* Pacing Info */}

Pacing Type

{plan.pacing.type.replace("-", " ")}

Average Cut Duration

{plan.pacing.averageCutDuration.toFixed(1)}s

Cut Range

{plan.pacing.cutDurationRange[0].toFixed(1)}s - {plan.pacing.cutDurationRange[1].toFixed(1)}s

Rhythm Complexity

{plan.pacing.rhythmComplexity}%

{/* Transitions Tab */} Transition Usage Types and frequency of transitions in your montage
{transitionUsage.length > 0 ? ( transitionUsage.map((usage: any) => (
{usage.transitionId.replace("-", " ")}
{usage.count}
)) ) : (

No transitions applied yet

)}
{/* Validation Tab */} Plan Validation Quality checks and potential issues {planValidation ? (
{planValidation.isValid ? ( <> Plan is valid ) : ( <> Issues detected )}
{planValidation.issues.length > 0 && (
{planValidation.issues.map((issue: any, index: number) => (
{issue.severity}

{issue.message}

))}
)} {planValidation.suggestions.length > 0 && (

Suggestions

{planValidation.suggestions.map((suggestion: any, index: number) => (

• {suggestion}

))}
)}
) : (

Run validation to check plan quality

)}
) }