File size: 8,216 Bytes
743409d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
import { useState } from 'react';
import { Upload, Image as ImageIcon, Loader2, Shield } from 'lucide-react';
import { Button } from './ui/button';
import { Card } from './ui/card';

interface UploadSectionProps {
  onAnalyze: (imageUrl: string) => void;
  isAnalyzing: boolean;
}

const SAMPLE_IMAGES = [
  {
    id: '1',
    name: 'Urgency & Scarcity Checkout',
    url: 'https://images.unsplash.com/photo-1563986768609-322da13575f3?w=800&q=80',
    description: 'Fintech checkout containing countdown timers and artificial item availability notifications.'
  },
  {
    id: '2',
    name: 'Pre-Selected Fees Flow',
    url: 'https://images.unsplash.com/photo-1551288049-bebda4e38f71?w=800&q=80',
    description: 'Trading account registration featuring pre-checked subscription add-ons and sneaking costs.'
  },
  {
    id: '3',
    name: 'Misdirecting Options Confirm',
    url: 'https://images.unsplash.com/photo-1460925895917-afdab827c52f?w=800&q=80',
    description: 'Subscription cancellation modal using guilt-inducing confirmshaming copywriting.'
  }
];

export function UploadSection({ onAnalyze, isAnalyzing }: UploadSectionProps) {
  const [selectedSample, setSelectedSample] = useState<string | null>(null);
  const [uploadedImage, setUploadedImage] = useState<string | null>(null);

  const handleFileUpload = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0];
    if (file) {
      const reader = new FileReader();
      reader.onload = (e) => {
        const result = e.target?.result as string;
        setUploadedImage(result);
        setSelectedSample(null);
      };
      reader.readAsDataURL(file);
    }
  };

  const handleSampleSelect = (url: string) => {
    setSelectedSample(url);
    setUploadedImage(null);
  };

  const handleAnalyze = () => {
    const imageUrl = uploadedImage || selectedSample;
    if (imageUrl) {
      onAnalyze(imageUrl);
    }
  };

  const activeImage = uploadedImage || selectedSample;

  return (
    <div className="space-y-6">
      <Card className="p-8 bg-card/40 backdrop-blur-md border border-border shadow-xl rounded-2xl relative overflow-hidden transition-colors duration-300">
        {/* Glow overlay */}
        <div className="absolute top-0 right-0 w-80 h-80 bg-indigo-500/10 rounded-full blur-3xl -z-10 pointer-events-none" />
        <div className="absolute bottom-0 left-0 w-80 h-80 bg-purple-500/5 rounded-full blur-3xl -z-10 pointer-events-none" />
        
        <h2 className="text-xl font-bold text-foreground mb-6 flex items-center gap-2">
          <Upload className="w-5 h-5 text-indigo-500 dark:text-indigo-400" />
          Audit New UI Interface
        </h2>
        
        <div className="grid md:grid-cols-2 gap-8">
          {/* Upload Area (Fits target image directly inside) */}
          <div className="space-y-4">
            <label
              htmlFor="file-upload"
              className={`relative flex flex-col items-center justify-center w-full h-72 border-2 border-dashed rounded-xl cursor-pointer overflow-hidden transition-all duration-300 ${
                isAnalyzing 
                  ? 'border-border bg-muted/10 cursor-not-allowed'
                  : activeImage
                    ? 'border-indigo-500/50 bg-slate-900/10 dark:bg-slate-950/40 shadow-inner'
                    : 'border-border bg-muted/20 hover:border-indigo-500/50 hover:bg-muted/40'
              }`}
            >
              {activeImage ? (
                <>
                  <img
                    src={activeImage}
                    alt="Uploaded UI Target"
                    className="w-full h-full object-contain p-2"
                  />
                  {/* Hover Overlay */}
                  <div className="absolute inset-0 bg-slate-950/50 opacity-0 hover:opacity-100 transition-opacity duration-300 flex flex-col items-center justify-center text-center p-4">
                    <Upload className="w-8 h-8 text-indigo-400 mb-2" />
                    <span className="text-xs font-extrabold text-white">Click or Drop to Replace Screenshot</span>
                  </div>
                  {/* Bottom Indicator badge */}
                  <div className="absolute bottom-2 left-2">
                    <span className="text-[9px] font-mono bg-indigo-600 text-white px-2.5 py-1 rounded-md uppercase tracking-wider font-extrabold shadow-lg border border-indigo-500/20">
                      Target Interface Loaded
                    </span>
                  </div>
                </>
              ) : (
                <div className="flex flex-col items-center justify-center pt-5 pb-6 px-4 text-center">
                  <div className="p-4 bg-indigo-500/5 rounded-2xl mb-4 border border-indigo-500/10">
                    <Upload className="w-10 h-10 text-indigo-500 dark:text-indigo-400 animate-pulse" />
                  </div>
                  <p className="mb-2 text-sm text-foreground/80">
                    <span className="font-semibold text-indigo-500 dark:text-indigo-400">Click to upload</span> or drag and drop
                  </p>
                  <p className="text-xs text-muted-foreground">PNG, JPG or GIF (MAX. 10MB)</p>
                </div>
              )}
              <input
                id="file-upload"
                type="file"
                className="hidden"
                accept="image/*"
                onChange={handleFileUpload}
                disabled={isAnalyzing}
              />
            </label>
          </div>

          {/* Sample Images */}
          <div className="space-y-4">
            <div className="flex items-center gap-2 mb-4">
              <ImageIcon className="w-5 h-5 text-indigo-500 dark:text-indigo-400" />
              <h3 className="font-semibold text-foreground">Select Fintech Sample Screen</h3>
            </div>
            
            <div className="space-y-3">
              {SAMPLE_IMAGES.map((sample) => (
                <button
                  key={sample.id}
                  onClick={() => handleSampleSelect(sample.url)}
                  disabled={isAnalyzing}
                  className={`w-full text-left p-4 rounded-xl border transition-all duration-300 relative overflow-hidden group ${
                    selectedSample === sample.url
                      ? 'border-indigo-500 bg-indigo-500/5 shadow-md shadow-indigo-500/5'
                      : 'border-border bg-muted/10 hover:border-slate-400 dark:hover:border-slate-700 hover:bg-muted/20'
                  } ${isAnalyzing ? 'opacity-50 cursor-not-allowed' : ''}`}
                >
                  <div className="font-bold text-sm text-foreground mb-1 group-hover:text-indigo-500 dark:group-hover:text-indigo-400 transition-colors">
                    {sample.name}
                  </div>
                  <div className="text-xs text-muted-foreground line-clamp-2 leading-relaxed">
                    {sample.description}
                  </div>
                </button>
              ))}
            </div>
          </div>
        </div>

        {/* Analyze Button */}
        <div className="mt-8 flex justify-center border-t border-border pt-6">
          <Button
            onClick={handleAnalyze}
            disabled={!activeImage || isAnalyzing}
            size="lg"
            className={`min-w-[240px] h-12 rounded-xl text-xs font-bold uppercase tracking-wider transition-all duration-300 ${
              !activeImage 
                ? 'bg-muted text-muted-foreground cursor-not-allowed border border-border' 
                : 'bg-gradient-to-r from-indigo-600 via-indigo-500 to-purple-600 hover:from-indigo-500 hover:to-purple-500 text-white shadow-[0_0_20px_rgba(99,102,241,0.3)] hover:scale-[1.03]'
            }`}
          >
            {isAnalyzing ? (
              <>
                <Loader2 className="w-5 h-5 mr-2 animate-spin text-white" />
                Processing AI Auditing...
              </>
            ) : (
              <>
                <Shield className="w-5 h-5 mr-2 text-white" />
                Analyze Deceptive Copywriting
              </>
            )}
          </Button>
        </div>
      </Card>
    </div>
  );
}