'use client'; import React, { useEffect, useMemo, useRef, useState } from 'react'; import { motion, AnimatePresence } from 'framer-motion'; import { Loader2 } from 'lucide-react'; interface ScriptLoadingProps { /** When true, progress snaps to 100% */ isCompleted?: boolean; /** Estimated total duration in ms to reach ~95% (default 80s) */ estimatedMs?: number; } /** * Dark-themed loading with spinner, staged copy and progress bar. * Progress linearly approaches 95% over estimatedMs, then snaps to 100% if isCompleted=true. */ export const ScriptLoading: React.FC = ({ isCompleted = false, estimatedMs = 80000 }) => { const [progress, setProgress] = useState(0); const intervalRef = useRef(null); const targetWhenPending = 95; // cap before data arrives const tickMs = 200; // update cadence // staged messages by progress const stageMessage = useMemo(() => { if (progress >= 100) return 'Done'; if (progress >= 95) return 'Almost done, please wait...'; if (progress >= 82) return 'Generating script and prompt...'; if (progress >= 63) return 'Polishing dialogue and transitions...'; if (progress >= 45) return 'Arranging shots and rhythm...'; if (progress >= 28) return 'Shaping characters and scene details...'; if (progress >= 12) return 'Outlining the story...'; return 'Waking up the creative engine...'; }, [progress]); // progress auto-increment useEffect(() => { const desiredTarget = isCompleted ? 100 : targetWhenPending; // when completed, quickly animate to 100 if (isCompleted) { setProgress((prev) => (prev < 100 ? Math.max(prev, 96) : 100)); } if (intervalRef.current) clearInterval(intervalRef.current); // compute linear increment to reach target in remaining estimated time const totalTicks = Math.ceil(estimatedMs / tickMs); const baseIncrement = (targetWhenPending - 0) / Math.max(totalTicks, 1); intervalRef.current = setInterval(() => { setProgress((prev) => { const target = isCompleted ? 100 : desiredTarget; if (prev >= target) return prev; const remaining = target - prev; const step = Math.max(Math.min(baseIncrement, remaining * 0.25), 0.2); const next = Math.min(prev + step, target); return Number(next.toFixed(2)); }); }, tickMs); return () => { if (intervalRef.current) clearInterval(intervalRef.current); }; }, [isCompleted, estimatedMs]); const widthStyle = { width: `${Math.min(progress, 100)}%` }; return (
{/* subtle animated halo */} {/*
*/} {stageMessage}
Generating Script... {Math.round(progress)}%
); }; export default ScriptLoading;