File size: 8,309 Bytes
370c714
 
1b7ad81
370c714
 
 
 
 
 
 
3fd02c0
370c714
3fd02c0
370c714
 
 
 
 
 
 
 
3fd02c0
 
 
370c714
 
3fd02c0
1b7ad81
370c714
 
 
 
 
 
809dc87
370c714
 
 
 
3fd02c0
 
 
 
 
 
 
 
 
 
 
 
370c714
809dc87
 
 
 
370c714
 
 
 
 
 
3fd02c0
370c714
809dc87
3fd02c0
370c714
 
 
 
 
 
 
3fd02c0
370c714
 
 
809dc87
370c714
 
3fd02c0
370c714
3fd02c0
370c714
3fd02c0
370c714
 
 
809dc87
370c714
 
 
 
3fd02c0
 
809dc87
 
3fd02c0
809dc87
3fd02c0
809dc87
3fd02c0
809dc87
3fd02c0
370c714
3fd02c0
1b7ad81
3fd02c0
 
 
 
 
 
 
 
 
 
 
 
 
809dc87
1b7ad81
809dc87
 
1b7ad81
 
 
 
 
 
809dc87
1b7ad81
 
 
 
 
 
 
 
 
 
370c714
 
 
3fd02c0
 
370c714
 
 
3fd02c0
370c714
3fd02c0
370c714
809dc87
370c714
3fd02c0
809dc87
370c714
 
 
 
 
 
 
 
 
3fd02c0
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
import React, { useEffect, useState } from 'react';
import { Product } from '../types';
import { RefreshCw, AlertCircle, Sparkles, ScanFace, Timer, Play, ChevronDown, ChevronUp, Bug } from 'lucide-react';

interface ResultViewProps {
  originalImage: string;
  generatedImage: string | null;
  product: Product;
  loading: boolean;
  error: string | null;
  retryAfter: number | null;
  onRetake: () => void;
  onRetry: () => void;
}

const ResultView: React.FC<ResultViewProps> = ({ 
  originalImage, 
  generatedImage, 
  product, 
  loading, 
  error,
  retryAfter,
  onRetake,
  onRetry
}) => {
  const [progressStep, setProgressStep] = useState(0);
  const [timeLeft, setTimeLeft] = useState<number | null>(null);
  const [showDetails, setShowDetails] = useState(false);

  useEffect(() => {
    if (loading) {
      setProgressStep(0);
      const interval = setInterval(() => {
        setProgressStep(prev => (prev < 3 ? prev + 1 : prev));
      }, 2000);
      return () => clearInterval(interval);
    }
  }, [loading]);

  useEffect(() => {
    if (retryAfter !== null) {
      setTimeLeft(retryAfter);
      const timer = setInterval(() => {
        setTimeLeft(prev => (prev !== null && prev > 0 ? prev - 1 : 0));
      }, 1000);
      return () => clearInterval(timer);
    } else {
      setTimeLeft(null);
    }
  }, [retryAfter]);

  const loadingTexts = [
    "Encoding micro-pixels...",
    "Analyzing garment...",
    "Synthesizing fit...",
    "Almost there..."
  ];

  return (
    <div className="min-h-screen bg-gray-50 flex flex-col">
      <div className="flex-1 max-w-4xl mx-auto w-full p-4 flex flex-col md:flex-row gap-6 items-start justify-center pt-8">
        
        {/* Sidebar Preview */}
        <div className="w-full md:w-1/3 bg-white p-3 rounded-2xl shadow-sm border border-gray-100 flex flex-col gap-2">
             <h3 className="text-xs font-bold text-gray-400 uppercase tracking-widest px-1">Source</h3>
             <div className="aspect-[3/4] rounded-xl overflow-hidden bg-gray-100 relative">
                 <img src={originalImage} alt="Original" className="w-full h-full object-cover" />
                 <div className="absolute bottom-2 right-2 bg-white/90 backdrop-blur rounded-lg p-1 shadow-sm w-12 h-12 border border-gray-200">
                     <img src={product.imageUrl} className="w-full h-full object-contain mix-blend-multiply" alt="item" />
                 </div>
             </div>
        </div>

        {/* Result Area */}
        <div className="w-full md:w-2/3 bg-white p-3 rounded-2xl shadow-lg border border-gray-100 flex flex-col gap-2 relative min-h-[400px]">
             <h3 className="text-sm font-semibold text-brand-600 uppercase tracking-wide px-1 flex items-center gap-2">
                 <Sparkles className="w-4 h-4 text-brand-500" />
                 AI Studio
             </h3>
             
             <div className="aspect-[3/4] md:aspect-square rounded-xl overflow-hidden bg-slate-900 relative flex items-center justify-center">
                 {loading && (
                     <div className="absolute inset-0 flex flex-col items-center justify-center bg-slate-900/90 backdrop-blur-md z-10 text-white p-6 text-center">
                         <div className="relative mb-6">
                            <div className="w-16 h-16 border-4 border-brand-500/20 rounded-full animate-pulse"></div>
                            <div className="absolute inset-0 w-16 h-16 border-4 border-brand-500 border-t-transparent rounded-full animate-spin"></div>
                            <ScanFace className="absolute inset-0 w-8 h-8 m-auto text-brand-500 animate-pulse" />
                         </div>
                         <h4 className="text-xl font-bold mb-2">Generating...</h4>
                         <p className="text-brand-300 font-medium animate-pulse">{loadingTexts[progressStep]}</p>
                     </div>
                 )}

                 {timeLeft !== null && (
                     <div className="absolute inset-0 flex flex-col items-center justify-center p-8 text-center bg-slate-900 text-white z-20">
                         <div className="bg-amber-500/20 p-5 rounded-full mb-6">
                            <Timer className="w-12 h-12 text-amber-400 animate-pulse" />
                         </div>
                         <h4 className="text-2xl font-bold mb-3 text-amber-400">AI Cooling Down</h4>
                         <p className="text-slate-400 text-sm mb-8 max-w-xs">
                             To prevent errors, please wait 2 minutes between attempts on the free tier.
                         </p>
                         <div className="text-6xl font-mono font-bold text-white mb-10">
                             {timeLeft}s
                         </div>
                         <div className="flex gap-4">
                            <button onClick={onRetake} className="px-6 py-3 bg-white/10 hover:bg-white/20 rounded-xl font-bold transition-all">Back</button>
                            <button 
                                onClick={onRetry} 
                                disabled={timeLeft > 0}
                                className={`px-8 py-3 rounded-xl font-bold flex items-center gap-2 transition-all ${timeLeft === 0 ? 'bg-brand-500 text-white' : 'bg-slate-700 text-slate-500 cursor-not-allowed'}`}
                            >
                                <Play className="w-4 h-4" />
                                Try Now
                            </button>
                         </div>
                     </div>
                 )}

                 {error && timeLeft === null && (
                     <div className="absolute inset-0 flex flex-col items-center justify-center p-8 text-center bg-slate-800">
                         <AlertCircle className="w-10 h-10 text-red-500 mb-4" />
                         <h4 className="text-white font-bold text-lg mb-2">Service Delay</h4>
                         <p className="text-gray-400 text-sm mb-6 px-4">The AI encountered a limit. Wait a moment then retry.</p>
                         
                         <button 
                            onClick={() => setShowDetails(!showDetails)}
                            className="flex items-center gap-2 text-[10px] text-gray-500 uppercase tracking-widest mb-4 hover:text-gray-300 transition-colors"
                         >
                            <Bug className="w-3 h-3" />
                            Diagnostics
                            {showDetails ? <ChevronUp className="w-3 h-3" /> : <ChevronDown className="w-3 h-3" />}
                         </button>

                         {showDetails && (
                             <div className="bg-black/50 p-3 rounded-lg border border-white/10 text-left mb-6 max-h-32 overflow-y-auto w-full">
                                 <code className="text-[10px] text-red-400 break-all">{error}</code>
                             </div>
                         )}

                         <button onClick={onRetake} className="px-8 py-3 bg-white text-black rounded-xl font-bold hover:bg-gray-100 transition-colors">Go Back</button>
                     </div>
                 )}

                 {!loading && !error && !timeLeft && generatedImage && (
                     <img src={generatedImage} alt="Result" className="w-full h-full object-contain animate-in fade-in zoom-in-95 duration-700" />
                 )}
             </div>

             {!loading && !error && !timeLeft && generatedImage && (
                 <div className="grid grid-cols-2 gap-3 mt-2">
                     <button onClick={onRetake} className="flex items-center justify-center gap-2 py-4 bg-slate-100 hover:bg-slate-200 text-slate-700 rounded-xl font-bold transition-all">
                         <RefreshCw className="w-4 h-4" />
                         Retake
                     </button>
                     <button className="flex items-center justify-center gap-2 py-4 bg-brand-600 hover:bg-brand-700 text-white rounded-xl font-bold transition-all shadow-lg shadow-brand-200">
                         Save
                     </button>
                 </div>
             )}
        </div>
      </div>
    </div>
  );
};

export default ResultView;