File size: 3,628 Bytes
91d209c
 
 
 
 
 
82a1419
 
 
 
91d209c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82a1419
91d209c
82a1419
91d209c
82a1419
 
91d209c
 
 
 
 
82a1419
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91d209c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
import { motion } from 'framer-motion';
import { useGeneration } from '@/context/GenerationContext';
import { XIcon, RefreshIcon, ArrowLeftIcon } from './Icons';

export const ErrorDisplay: React.FC = () => {
  const { state, reset, setStep } = useGeneration();
  const { error, generatedVideos, segments } = state;
  const isCancelled = error?.toLowerCase().includes('cancelled') ?? false;
  const hasPartialVideos = generatedVideos.length > 0;
  const hasPartialPrompts = segments.length > 0 && !hasPartialVideos;

  return (
    <motion.div
      initial={{ opacity: 0 }}
      animate={{ opacity: 1 }}
      className="min-h-[60vh] flex flex-col items-center justify-center p-8"
    >
      <div className="max-w-lg w-full text-center">
        {/* Error Icon */}
        <motion.div
          initial={{ scale: 0 }}
          animate={{ scale: 1 }}
          transition={{ type: 'spring', duration: 0.5 }}
          className="w-20 h-20 mx-auto rounded-full bg-red-500/20 flex items-center justify-center mb-6"
        >
          <XIcon size={40} className="text-red-400" />
        </motion.div>

        {/* Title: Cancelled vs Failed */}
        <h1 className="text-3xl font-display font-bold text-void-100 mb-4">
          {isCancelled ? 'Generation Cancelled' : 'Generation Failed'}
        </h1>

        <div className="card bg-red-500/10 border-red-500/30 mb-4">
          <p className="text-red-300 text-sm">
            {error || 'An unexpected error occurred during video generation.'}
          </p>
        </div>

        {/* Partial results when user cancelled */}
        {(isCancelled && (hasPartialVideos || hasPartialPrompts)) && (
          <div className="card bg-void-900/80 border-void-600 mb-8 text-left">
            <h3 className="text-sm font-semibold text-void-200 mb-2">Stopped with partial results</h3>
            {hasPartialVideos && (
              <p className="text-void-300 text-sm">
                <span className="font-medium text-void-100">{generatedVideos.length}</span> video segment{generatedVideos.length === 1 ? '' : 's'} generated.
              </p>
            )}
            {hasPartialPrompts && (
              <p className="text-void-300 text-sm mt-1">
                <span className="font-medium text-void-100">{segments.length}</span> segment prompt{segments.length === 1 ? '' : 's'} generated (no videos yet).
              </p>
            )}
          </div>
        )}

        {/* Actions */}
        <div className="flex flex-col sm:flex-row items-center justify-center gap-4">
          <button
            onClick={() => setStep('configuring')}
            className="btn-primary flex items-center gap-2"
          >
            <RefreshIcon size={20} />
            Try Again
          </button>
          
          <button
            onClick={reset}
            className="btn-secondary flex items-center gap-2"
          >
            <ArrowLeftIcon size={20} />
            Start Over
          </button>
        </div>

        {/* Help Text */}
        <div className="mt-8 p-4 bg-void-900/50 rounded-xl border border-void-700">
          <h3 className="text-sm font-semibold text-void-300 mb-2">Troubleshooting Tips</h3>
          <ul className="text-xs text-void-400 space-y-1 text-left">
            <li>• Check that your API keys are properly configured</li>
            <li>• Ensure your image is under 10MB and in JPG/PNG format</li>
            <li>• Try a shorter script if timeouts occur</li>
            <li>• Check the backend server logs for more details</li>
          </ul>
        </div>
      </div>
    </motion.div>
  );
};