File size: 3,316 Bytes
7017720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ea6c2a8
7017720
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ea6c2a8
 
 
 
 
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
92
93
94
95
import { useState, useEffect } from "react";

/**
 * Enhanced loading component with visual feedback
 * 
 * Features:
 * - Progress indicator with percentage display
 * - Animated loading spinner
 * - Progress bar visualization
 * - Contextual status messages
 * - Animated ellipsis for active feedback
 * 
 * @param progress - Current progress percentage (0-100)
 * @param showDetails - Whether to show detailed status messages
 */
function Loading({ progress = 0, showDetails = false }: { progress?: number; showDetails?: boolean }) {
  const [dots, setDots] = useState("");
  
  // Animated dots for the loading text (provides visual feedback even when progress is unknown)
  useEffect(() => {
    const interval = setInterval(() => {
      setDots(prev => (prev.length >= 3 ? "" : prev + "."));
    }, 400);
    return () => clearInterval(interval);
  }, []);
  
  // Get appropriate status message based on current progress
  const getStatusMessage = () => {
    if (progress < 25) return "Analyzing request...";
    if (progress < 50) return "Generating content...";
    if (progress < 75) return "Processing changes...";
    if (progress < 100) return "Finalizing...";
    return "Complete!";
  };

  return (
    <div className="absolute left-0 top-0 h-full w-full flex flex-col items-center justify-center bg-gray-950/90 backdrop-blur-sm z-20">
      <div className="relative">
        {/* Progress circle with animated spin */}
        <svg
          className="size-16 animate-spin text-purple-400"
          xmlns="http://www.w3.org/2000/svg"
          fill="none"
          viewBox="0 0 24 24"
        >
          <circle
            className="opacity-25"
            cx="12"
            cy="12"
            r="10"
            stroke="currentColor"
            strokeWidth="4"
          ></circle>
          <path
            className="opacity-75"
            fill="currentColor"
            d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
          ></path>
        </svg>
        
        {/* Progress percentage in center - only shown when progress is known */}
        {progress > 0 && (
          <div className="absolute inset-0 flex items-center justify-center">
            <span className="text-sm font-bold text-white">{progress}%</span>
          </div>
        )}
      </div>
      
      <div className="mt-4 flex flex-col items-center">
        {/* Main loading message with animated dots */}
        <p className="text-lg font-bold text-purple-200 mb-1">AI is thinking{dots}</p>
        
        {/* Horizontal progress bar - only shown when progress is known */}
        {progress > 0 && (
          <div className="w-48 h-1.5 bg-gray-700 rounded-full overflow-hidden mt-2">
            <div 
              className="h-full bg-gradient-to-r from-purple-400 to-pink-500 transition-all duration-300 ease-out"
              style={{ width: `${progress}%` }}
            />
          </div>
        )}
        
        {/* Optional detailed status message - shows processing stage */}
        {showDetails && (
          <p className="mt-2 text-xs text-purple-300/80 max-w-xs text-center animate-pulse">
            {getStatusMessage()}
          </p>
        )}
      </div>
    </div>
  );
}

export default Loading;