shashwatIDR commited on
Commit
ea94f5e
·
verified ·
1 Parent(s): 01c681c

Upload index.html

Browse files
Files changed (1) hide show
  1. public/index.html +709 -0
public/index.html ADDED
@@ -0,0 +1,709 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>AI Image Creator - Next Gen</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet">
9
+ <script>
10
+ tailwind.config = {
11
+ theme: {
12
+ extend: {
13
+ colors: {
14
+ 'neon-blue': '#00d4ff',
15
+ 'neon-purple': '#8b5cf6',
16
+ 'neon-pink': '#ec4899',
17
+ 'dark-bg': '#0a0a0a',
18
+ 'card-bg': '#1a1a1a',
19
+ 'border-glow': '#00d4ff40'
20
+ },
21
+ animation: {
22
+ 'float': 'float 6s ease-in-out infinite',
23
+ 'glow': 'glow 2s ease-in-out infinite alternate',
24
+ 'pulse-slow': 'pulse 3s cubic-bezier(0.4, 0, 0.6, 1) infinite',
25
+ }
26
+ }
27
+ }
28
+ }
29
+ </script>
30
+ <style>
31
+ @keyframes float {
32
+ 0%, 100% { transform: translateY(0px); }
33
+ 50% { transform: translateY(-20px); }
34
+ }
35
+ @keyframes glow {
36
+ from { box-shadow: 0 0 20px #00d4ff; }
37
+ to { box-shadow: 0 0 30px #00d4ff, 0 0 40px #00d4ff; }
38
+ }
39
+ .gradient-text {
40
+ background: linear-gradient(45deg, #00d4ff, #8b5cf6, #ec4899);
41
+ -webkit-background-clip: text;
42
+ -webkit-text-fill-color: transparent;
43
+ background-clip: text;
44
+ }
45
+ .glass-effect {
46
+ background: rgba(255, 255, 255, 0.05);
47
+ backdrop-filter: blur(10px);
48
+ border: 1px solid rgba(255, 255, 255, 0.1);
49
+ }
50
+ .neon-border {
51
+ border: 1px solid #00d4ff;
52
+ box-shadow: 0 0 10px #00d4ff40;
53
+ }
54
+ .neon-border:hover {
55
+ box-shadow: 0 0 20px #00d4ff, 0 0 30px #00d4ff40;
56
+ }
57
+ </style>
58
+ </head>
59
+ <body class="bg-dark-bg text-white min-h-screen font-sans">
60
+ <!-- Navigation -->
61
+ <nav class="glass-effect fixed top-0 w-full z-50 border-b border-white/10">
62
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
63
+ <div class="flex justify-between items-center h-16">
64
+ <div class="flex items-center space-x-4">
65
+ <div class="w-10 h-10 bg-gradient-to-r from-neon-blue to-neon-purple rounded-lg flex items-center justify-center animate-pulse-slow">
66
+ <i class="fas fa-magic text-white text-lg"></i>
67
+ </div>
68
+ <h1 class="text-2xl font-bold gradient-text">AI Creator</h1>
69
+ </div>
70
+ <div class="hidden md:flex items-center space-x-6">
71
+ <button onclick="showSection('create')" class="nav-btn text-gray-300 hover:text-neon-blue transition-colors">
72
+ <i class="fas fa-plus mr-2"></i>Create
73
+ </button>
74
+ <button onclick="showSection('gallery')" class="nav-btn text-gray-300 hover:text-neon-blue transition-colors">
75
+ <i class="fas fa-images mr-2"></i>Gallery
76
+ </button>
77
+ <button onclick="showSection('history')" class="nav-btn text-gray-300 hover:text-neon-blue transition-colors">
78
+ <i class="fas fa-history mr-2"></i>History
79
+ </button>
80
+ <button id="authBtn" onclick="showAuthModal()" class="px-6 py-2 bg-gradient-to-r from-neon-blue to-neon-purple rounded-full hover:opacity-90 transition-opacity">
81
+ <i class="fas fa-sign-in-alt mr-2"></i>Login
82
+ </button>
83
+ </div>
84
+ <div class="md:hidden">
85
+ <button onclick="toggleMobileMenu()" class="text-gray-300 hover:text-neon-blue">
86
+ <i class="fas fa-bars text-xl"></i>
87
+ </button>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </nav>
92
+
93
+ <!-- Mobile Menu -->
94
+ <div id="mobileMenu" class="md:hidden fixed top-16 left-0 w-full glass-effect border-b border-white/10 hidden">
95
+ <div class="px-4 py-4 space-y-4">
96
+ <button onclick="showSection('create')" class="nav-btn w-full text-left text-gray-300 hover:text-neon-blue transition-colors">
97
+ <i class="fas fa-plus mr-2"></i>Create
98
+ </button>
99
+ <button onclick="showSection('gallery')" class="nav-btn w-full text-left text-gray-300 hover:text-neon-blue transition-colors">
100
+ <i class="fas fa-images mr-2"></i>Gallery
101
+ </button>
102
+ <button onclick="showSection('history')" class="nav-btn w-full text-left text-gray-300 hover:text-neon-blue transition-colors">
103
+ <i class="fas fa-history mr-2"></i>History
104
+ </button>
105
+ <button onclick="showAuthModal()" class="w-full px-6 py-2 bg-gradient-to-r from-neon-blue to-neon-purple rounded-full hover:opacity-90 transition-opacity">
106
+ <i class="fas fa-sign-in-alt mr-2"></i>Login
107
+ </button>
108
+ </div>
109
+ </div>
110
+
111
+ <!-- Main Content -->
112
+ <main class="pt-20">
113
+ <!-- Create Section -->
114
+ <section id="createSection" class="section active min-h-screen">
115
+ <div class="max-w-4xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
116
+ <!-- Hero Section -->
117
+ <div class="text-center mb-16">
118
+ <h2 class="text-6xl font-bold gradient-text mb-6 animate-float">
119
+ Create Magic
120
+ </h2>
121
+ <p class="text-xl text-gray-400 mb-8 max-w-2xl mx-auto">
122
+ Transform your imagination into stunning visuals with our advanced AI image generation
123
+ </p>
124
+ <div class="flex justify-center space-x-4">
125
+ <div class="w-4 h-4 bg-neon-blue rounded-full animate-pulse"></div>
126
+ <div class="w-4 h-4 bg-neon-purple rounded-full animate-pulse" style="animation-delay: 0.2s;"></div>
127
+ <div class="w-4 h-4 bg-neon-pink rounded-full animate-pulse" style="animation-delay: 0.4s;"></div>
128
+ </div>
129
+ </div>
130
+
131
+ <!-- Creation Interface -->
132
+ <div class="glass-effect rounded-3xl p-8 neon-border">
133
+ <div class="space-y-8">
134
+ <!-- Prompt Input -->
135
+ <div class="relative">
136
+ <textarea id="promptInput"
137
+ class="w-full h-32 bg-card-bg border border-white/20 rounded-2xl px-6 py-4 text-white placeholder-gray-500 focus:outline-none focus:border-neon-blue focus:ring-2 focus:ring-neon-blue/20 resize-none"
138
+ placeholder="Describe your vision... What would you like to create?"></textarea>
139
+ <div class="absolute bottom-4 right-4">
140
+ <button id="generateBtn" onclick="generateImage()"
141
+ class="px-8 py-3 bg-gradient-to-r from-neon-blue to-neon-purple rounded-full font-semibold hover:opacity-90 transition-opacity animate-glow">
142
+ <i class="fas fa-magic mr-2"></i>Generate
143
+ </button>
144
+ </div>
145
+ </div>
146
+
147
+ <!-- Quick Prompts -->
148
+ <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
149
+ <button onclick="setPrompt('A futuristic city with flying cars and neon lights')"
150
+ class="quick-prompt glass-effect rounded-xl p-4 hover:neon-border transition-all">
151
+ <i class="fas fa-city text-neon-blue mb-2"></i>
152
+ <p class="text-sm">Futuristic City</p>
153
+ </button>
154
+ <button onclick="setPrompt('A magical forest with glowing mushrooms and fairy lights')"
155
+ class="quick-prompt glass-effect rounded-xl p-4 hover:neon-border transition-all">
156
+ <i class="fas fa-tree text-neon-purple mb-2"></i>
157
+ <p class="text-sm">Magical Forest</p>
158
+ </button>
159
+ <button onclick="setPrompt('A cyberpunk warrior with neon armor and glowing weapons')"
160
+ class="quick-prompt glass-effect rounded-xl p-4 hover:neon-border transition-all">
161
+ <i class="fas fa-user-ninja text-neon-pink mb-2"></i>
162
+ <p class="text-sm">Cyberpunk Warrior</p>
163
+ </button>
164
+ <button onclick="setPrompt('An underwater palace with coral and sea creatures')"
165
+ class="quick-prompt glass-effect rounded-xl p-4 hover:neon-border transition-all">
166
+ <i class="fas fa-water text-neon-blue mb-2"></i>
167
+ <p class="text-sm">Underwater Palace</p>
168
+ </button>
169
+ </div>
170
+
171
+ <!-- Loading State -->
172
+ <div id="loadingState" class="hidden text-center py-12">
173
+ <div class="inline-flex items-center space-x-4">
174
+ <div class="w-8 h-8 border-4 border-neon-blue border-t-transparent rounded-full animate-spin"></div>
175
+ <span class="text-neon-blue text-lg">Creating your masterpiece...</span>
176
+ </div>
177
+ <div id="queueInfo" class="mt-4 text-gray-400"></div>
178
+ </div>
179
+
180
+ <!-- Result -->
181
+ <div id="resultSection" class="hidden">
182
+ <div class="glass-effect rounded-2xl p-6 neon-border">
183
+ <img id="generatedImage" class="w-full rounded-xl shadow-2xl" alt="Generated image">
184
+ <div class="mt-6 flex justify-between items-center">
185
+ <button onclick="addToGallery()" class="px-6 py-3 bg-gradient-to-r from-neon-purple to-neon-pink rounded-full hover:opacity-90 transition-opacity">
186
+ <i class="fas fa-plus mr-2"></i>Add to Gallery
187
+ </button>
188
+ <button onclick="downloadImage()" class="px-6 py-3 glass-effect rounded-full hover:neon-border transition-all">
189
+ <i class="fas fa-download mr-2"></i>Download
190
+ </button>
191
+ </div>
192
+ </div>
193
+ </div>
194
+ </div>
195
+ </div>
196
+ </div>
197
+ </section>
198
+
199
+ <!-- Gallery Section -->
200
+ <section id="gallerySection" class="section hidden min-h-screen">
201
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
202
+ <div class="text-center mb-12">
203
+ <h2 class="text-5xl font-bold gradient-text mb-4">Community Gallery</h2>
204
+ <p class="text-xl text-gray-400">Explore amazing creations from our community</p>
205
+ </div>
206
+
207
+ <div class="flex justify-center mb-8">
208
+ <select id="sortOrder" onchange="loadGallery()" class="glass-effect rounded-full px-6 py-3 border border-white/20 focus:outline-none focus:border-neon-blue">
209
+ <option value="new-old">Newest First</option>
210
+ <option value="old-new">Oldest First</option>
211
+ </select>
212
+ </div>
213
+
214
+ <div id="galleryGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
215
+ <!-- Gallery items will be loaded here -->
216
+ </div>
217
+ </div>
218
+ </section>
219
+
220
+ <!-- History Section -->
221
+ <section id="historySection" class="section hidden min-h-screen">
222
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
223
+ <div class="text-center mb-12">
224
+ <h2 class="text-5xl font-bold gradient-text mb-4">Your Creations</h2>
225
+ <p class="text-xl text-gray-400">Your personal collection of generated images</p>
226
+ </div>
227
+
228
+ <div id="historyGrid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-6">
229
+ <!-- History items will be loaded here -->
230
+ </div>
231
+ </div>
232
+ </section>
233
+ </main>
234
+
235
+ <!-- Auth Modal -->
236
+ <div id="authModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
237
+ <div class="min-h-screen flex items-center justify-center p-4">
238
+ <div class="glass-effect rounded-3xl border border-white/20 w-full max-w-md neon-border">
239
+ <div class="p-8">
240
+ <div class="text-center mb-8">
241
+ <div class="w-16 h-16 bg-gradient-to-r from-neon-blue to-neon-purple rounded-full flex items-center justify-center mx-auto mb-4 animate-pulse-slow">
242
+ <i class="fas fa-user text-white text-2xl"></i>
243
+ </div>
244
+ <h3 class="text-2xl font-bold gradient-text" id="authTitle">Login</h3>
245
+ </div>
246
+
247
+ <!-- Login Form -->
248
+ <form id="loginForm" class="space-y-6">
249
+ <div>
250
+ <input type="email" id="loginEmail" placeholder="Email" required
251
+ class="w-full bg-card-bg border border-white/20 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:border-neon-blue">
252
+ </div>
253
+ <div>
254
+ <input type="password" id="loginPassword" placeholder="Password" required
255
+ class="w-full bg-card-bg border border-white/20 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:border-neon-blue">
256
+ </div>
257
+ <button type="submit"
258
+ class="w-full px-6 py-3 bg-gradient-to-r from-neon-blue to-neon-purple rounded-xl font-semibold hover:opacity-90 transition-opacity">
259
+ Login
260
+ </button>
261
+ </form>
262
+
263
+ <!-- Register Form -->
264
+ <form id="registerForm" class="space-y-6 hidden">
265
+ <div>
266
+ <input type="text" id="registerUsername" placeholder="Username" required
267
+ class="w-full bg-card-bg border border-white/20 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:border-neon-blue">
268
+ </div>
269
+ <div>
270
+ <input type="email" id="registerEmail" placeholder="Email" required
271
+ class="w-full bg-card-bg border border-white/20 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:border-neon-blue">
272
+ </div>
273
+ <div>
274
+ <input type="password" id="registerPassword" placeholder="Password" required
275
+ class="w-full bg-card-bg border border-white/20 rounded-xl px-4 py-3 text-white placeholder-gray-500 focus:outline-none focus:border-neon-blue">
276
+ </div>
277
+ <button type="submit"
278
+ class="w-full px-6 py-3 bg-gradient-to-r from-neon-purple to-neon-pink rounded-xl font-semibold hover:opacity-90 transition-opacity">
279
+ Register
280
+ </button>
281
+ </form>
282
+
283
+ <div class="text-center mt-6">
284
+ <button onclick="toggleAuthForm()" class="text-neon-blue hover:text-neon-purple transition-colors" id="toggleAuthBtn">
285
+ Don't have an account? Register
286
+ </button>
287
+ </div>
288
+
289
+ <button onclick="closeAuthModal()" class="absolute top-4 right-4 text-gray-400 hover:text-white">
290
+ <i class="fas fa-times text-xl"></i>
291
+ </button>
292
+ </div>
293
+ </div>
294
+ </div>
295
+ </div>
296
+
297
+ <!-- Image Preview Modal -->
298
+ <div id="previewModal" class="fixed inset-0 bg-black/50 backdrop-blur-sm hidden z-50">
299
+ <div class="min-h-screen flex items-center justify-center p-4">
300
+ <div class="glass-effect rounded-3xl border border-white/20 w-full max-w-4xl neon-border">
301
+ <div class="p-8">
302
+ <div class="flex justify-between items-center mb-6">
303
+ <h3 class="text-2xl font-bold gradient-text">Image Preview</h3>
304
+ <button onclick="closePreviewModal()" class="text-gray-400 hover:text-white">
305
+ <i class="fas fa-times text-xl"></i>
306
+ </button>
307
+ </div>
308
+ <img id="previewImage" class="w-full rounded-2xl shadow-2xl" alt="Preview">
309
+ <p id="previewPrompt" class="mt-4 text-center text-gray-300"></p>
310
+ </div>
311
+ </div>
312
+ </div>
313
+ </div>
314
+
315
+ <script>
316
+ let currentUser = null;
317
+ let currentToken = null;
318
+ let generatedImageUrl = null;
319
+
320
+ // Navigation
321
+ function showSection(sectionName) {
322
+ document.querySelectorAll('.section').forEach(s => s.classList.add('hidden'));
323
+ document.getElementById(sectionName + 'Section').classList.remove('hidden');
324
+
325
+ if (sectionName === 'gallery') loadGallery();
326
+ if (sectionName === 'history') loadHistory();
327
+ }
328
+
329
+ function toggleMobileMenu() {
330
+ const menu = document.getElementById('mobileMenu');
331
+ menu.classList.toggle('hidden');
332
+ }
333
+
334
+ // Auth Functions
335
+ async function checkAuth() {
336
+ const token = localStorage.getItem('token');
337
+ if (!token) {
338
+ updateAuthUI(false);
339
+ return;
340
+ }
341
+
342
+ try {
343
+ const response = await fetch('https://gen-image-main.vercel.app/api/auth/status', {
344
+ headers: { 'Authorization': `Bearer ${token}` }
345
+ });
346
+
347
+ if (response.ok) {
348
+ const data = await response.json();
349
+ currentUser = data.user;
350
+ currentToken = token;
351
+ updateAuthUI(true);
352
+ } else {
353
+ updateAuthUI(false);
354
+ }
355
+ } catch (error) {
356
+ updateAuthUI(false);
357
+ }
358
+ }
359
+
360
+ function updateAuthUI(isAuthenticated) {
361
+ const authBtn = document.getElementById('authBtn');
362
+ if (isAuthenticated) {
363
+ authBtn.innerHTML = `<i class="fas fa-user mr-2"></i>${currentUser.username}`;
364
+ authBtn.onclick = logout;
365
+ } else {
366
+ authBtn.innerHTML = `<i class="fas fa-sign-in-alt mr-2"></i>Login`;
367
+ authBtn.onclick = showAuthModal;
368
+ }
369
+ }
370
+
371
+ function showAuthModal() {
372
+ document.getElementById('authModal').classList.remove('hidden');
373
+ }
374
+
375
+ function closeAuthModal() {
376
+ document.getElementById('authModal').classList.add('hidden');
377
+ }
378
+
379
+ function toggleAuthForm() {
380
+ const loginForm = document.getElementById('loginForm');
381
+ const registerForm = document.getElementById('registerForm');
382
+ const authTitle = document.getElementById('authTitle');
383
+ const toggleBtn = document.getElementById('toggleAuthBtn');
384
+
385
+ if (loginForm.classList.contains('hidden')) {
386
+ loginForm.classList.remove('hidden');
387
+ registerForm.classList.add('hidden');
388
+ authTitle.textContent = 'Login';
389
+ toggleBtn.textContent = "Don't have an account? Register";
390
+ } else {
391
+ loginForm.classList.add('hidden');
392
+ registerForm.classList.remove('hidden');
393
+ authTitle.textContent = 'Register';
394
+ toggleBtn.textContent = 'Already have an account? Login';
395
+ }
396
+ }
397
+
398
+ async function login(event) {
399
+ event.preventDefault();
400
+ const email = document.getElementById('loginEmail').value;
401
+ const password = document.getElementById('loginPassword').value;
402
+
403
+ try {
404
+ const response = await fetch('https://gen-image-main.vercel.app/api/login', {
405
+ method: 'POST',
406
+ headers: { 'Content-Type': 'application/json' },
407
+ body: JSON.stringify({ email, password })
408
+ });
409
+
410
+ if (response.ok) {
411
+ const data = await response.json();
412
+ localStorage.setItem('token', data.token);
413
+ currentUser = data.user;
414
+ currentToken = data.token;
415
+ updateAuthUI(true);
416
+ closeAuthModal();
417
+ } else {
418
+ const error = await response.json();
419
+ alert(error.error);
420
+ }
421
+ } catch (error) {
422
+ alert('Login failed');
423
+ }
424
+ }
425
+
426
+ async function register(event) {
427
+ event.preventDefault();
428
+ const username = document.getElementById('registerUsername').value;
429
+ const email = document.getElementById('registerEmail').value;
430
+ const password = document.getElementById('registerPassword').value;
431
+
432
+ try {
433
+ const response = await fetch('https://gen-image-main.vercel.app/api/register', {
434
+ method: 'POST',
435
+ headers: { 'Content-Type': 'application/json' },
436
+ body: JSON.stringify({ username, email, password })
437
+ });
438
+
439
+ if (response.ok) {
440
+ const data = await response.json();
441
+ localStorage.setItem('token', data.token);
442
+ currentUser = data.user;
443
+ currentToken = data.token;
444
+ updateAuthUI(true);
445
+ closeAuthModal();
446
+ } else {
447
+ const error = await response.json();
448
+ alert(error.error);
449
+ }
450
+ } catch (error) {
451
+ alert('Registration failed');
452
+ }
453
+ }
454
+
455
+ function logout() {
456
+ localStorage.removeItem('token');
457
+ currentUser = null;
458
+ currentToken = null;
459
+ updateAuthUI(false);
460
+ }
461
+
462
+ // Image Generation
463
+ function setPrompt(prompt) {
464
+ document.getElementById('promptInput').value = prompt;
465
+ }
466
+
467
+ async function generateImage() {
468
+ const prompt = document.getElementById('promptInput').value.trim();
469
+ if (!prompt) {
470
+ alert('Please enter a prompt');
471
+ return;
472
+ }
473
+
474
+ if (!currentToken) {
475
+ alert('Please login to generate images');
476
+ return;
477
+ }
478
+
479
+ document.getElementById('loadingState').classList.remove('hidden');
480
+ document.getElementById('resultSection').classList.add('hidden');
481
+
482
+ try {
483
+ const response = await fetch('https://gen-image-main.vercel.app/api/generate', {
484
+ method: 'POST',
485
+ headers: {
486
+ 'Authorization': `Bearer ${currentToken}`,
487
+ 'Content-Type': 'application/json'
488
+ },
489
+ body: JSON.stringify({ prompt })
490
+ });
491
+
492
+ const reader = response.body.getReader();
493
+ const decoder = new TextDecoder();
494
+
495
+ while (true) {
496
+ const { done, value } = await reader.read();
497
+ if (done) break;
498
+
499
+ const chunk = decoder.decode(value);
500
+ const lines = chunk.split('\n');
501
+
502
+ for (const line of lines) {
503
+ if (line.startsWith('data: ')) {
504
+ try {
505
+ const data = JSON.parse(line.substring(6));
506
+
507
+ if (data.type === 'estimation') {
508
+ document.getElementById('queueInfo').textContent =
509
+ `Queue position: ${data.queueSize}, ETA: ${data.eta}s`;
510
+ } else if (data.type === 'processing') {
511
+ document.getElementById('queueInfo').textContent = 'Processing your image...';
512
+ } else if (data.type === 'success') {
513
+ generatedImageUrl = data.originalUrl;
514
+ document.getElementById('generatedImage').src = data.originalUrl;
515
+ document.getElementById('loadingState').classList.add('hidden');
516
+ document.getElementById('resultSection').classList.remove('hidden');
517
+ return;
518
+ } else if (data.type === 'error') {
519
+ throw new Error(data.message);
520
+ }
521
+ } catch (e) {
522
+ console.error('Error parsing SSE data:', e);
523
+ }
524
+ }
525
+ }
526
+ }
527
+ } catch (error) {
528
+ document.getElementById('loadingState').classList.add('hidden');
529
+ alert('Generation failed: ' + error.message);
530
+ }
531
+ }
532
+
533
+ async function addToGallery() {
534
+ if (!generatedImageUrl) return;
535
+
536
+ try {
537
+ const response = await fetch('https://gen-image-main.vercel.app/api/upload-image', {
538
+ method: 'POST',
539
+ headers: {
540
+ 'Authorization': `Bearer ${currentToken}`,
541
+ 'Content-Type': 'application/json'
542
+ },
543
+ body: JSON.stringify({
544
+ imageUrl: generatedImageUrl,
545
+ prompt: document.getElementById('promptInput').value
546
+ })
547
+ });
548
+
549
+ if (response.ok) {
550
+ alert('Image added to gallery successfully!');
551
+ loadGallery();
552
+ } else {
553
+ const error = await response.json();
554
+ alert(error.error);
555
+ }
556
+ } catch (error) {
557
+ alert('Failed to add to gallery');
558
+ }
559
+ }
560
+
561
+ function downloadImage() {
562
+ if (!generatedImageUrl) return;
563
+
564
+ const link = document.createElement('a');
565
+ link.href = generatedImageUrl;
566
+ link.download = 'generated-image.jpg';
567
+ link.click();
568
+ }
569
+
570
+ // Gallery Functions
571
+ async function loadGallery() {
572
+ try {
573
+ const response = await fetch('https://gen-image-main.vercel.app/api/community-images');
574
+ const images = await response.json();
575
+
576
+ const grid = document.getElementById('galleryGrid');
577
+ grid.innerHTML = '';
578
+
579
+ const sortOrder = document.getElementById('sortOrder').value;
580
+ const sortedImages = [...images].sort((a, b) => {
581
+ const dateA = new Date(a.created_at);
582
+ const dateB = new Date(b.created_at);
583
+ return sortOrder === 'old-new' ? dateA - dateB : dateB - dateA;
584
+ });
585
+
586
+ sortedImages.forEach(image => {
587
+ const card = createImageCard(image);
588
+ grid.appendChild(card);
589
+ });
590
+ } catch (error) {
591
+ console.error('Failed to load gallery:', error);
592
+ }
593
+ }
594
+
595
+ async function loadHistory() {
596
+ if (!currentToken) return;
597
+
598
+ try {
599
+ const response = await fetch('https://gen-image-main.vercel.app/api/user-generations', {
600
+ headers: { 'Authorization': `Bearer ${currentToken}` }
601
+ });
602
+
603
+ if (response.ok) {
604
+ const images = await response.json();
605
+ const grid = document.getElementById('historyGrid');
606
+ grid.innerHTML = '';
607
+
608
+ if (images.length === 0) {
609
+ grid.innerHTML = `
610
+ <div class="col-span-full text-center py-12">
611
+ <div class="w-24 h-24 bg-gradient-to-r from-neon-blue to-neon-purple rounded-full flex items-center justify-center mx-auto mb-4 animate-pulse-slow">
612
+ <i class="fas fa-magic text-white text-3xl"></i>
613
+ </div>
614
+ <p class="text-gray-400 text-lg">No images generated yet. Start creating!</p>
615
+ </div>
616
+ `;
617
+ return;
618
+ }
619
+
620
+ images.forEach(image => {
621
+ const card = createImageCard(image, true);
622
+ grid.appendChild(card);
623
+ });
624
+ }
625
+ } catch (error) {
626
+ console.error('Failed to load history:', error);
627
+ }
628
+ }
629
+
630
+ function createImageCard(image, isHistory = false) {
631
+ const card = document.createElement('div');
632
+ card.className = 'glass-effect rounded-2xl overflow-hidden neon-border hover:animate-glow transition-all cursor-pointer';
633
+
634
+ card.innerHTML = `
635
+ <div class="aspect-square overflow-hidden">
636
+ <img src="${image.uploaded_url || image.image_url}" alt="${image.prompt}"
637
+ class="w-full h-full object-cover hover:scale-105 transition-transform duration-300">
638
+ </div>
639
+ <div class="p-4 space-y-3">
640
+ <p class="text-gray-300 line-clamp-2 text-sm">${image.prompt}</p>
641
+ <div class="flex items-center justify-between text-xs">
642
+ <p class="text-neon-blue flex items-center">
643
+ <i class="fas fa-user mr-1"></i>${image.username || 'You'}
644
+ </p>
645
+ <p class="text-gray-500 flex items-center">
646
+ <i class="fas fa-clock mr-1"></i>${new Date(image.created_at).toLocaleDateString()}
647
+ </p>
648
+ </div>
649
+ ${isHistory ? `
650
+ <button onclick="deleteImage(${image.id})"
651
+ class="w-full mt-2 px-4 py-2 bg-red-500/20 text-red-400 rounded-xl hover:bg-red-500/30 transition-colors text-sm">
652
+ <i class="fas fa-trash mr-2"></i>Delete
653
+ </button>
654
+ ` : ''}
655
+ </div>
656
+ `;
657
+
658
+ card.querySelector('img').addEventListener('click', () => {
659
+ document.getElementById('previewImage').src = image.uploaded_url || image.image_url;
660
+ document.getElementById('previewPrompt').textContent = image.prompt;
661
+ document.getElementById('previewModal').classList.remove('hidden');
662
+ });
663
+
664
+ return card;
665
+ }
666
+
667
+ async function deleteImage(imageId) {
668
+ if (!confirm('Are you sure you want to delete this image?')) return;
669
+
670
+ try {
671
+ const response = await fetch(`https://gen-image-main.vercel.app/api/user-generations/${imageId}`, {
672
+ method: 'DELETE',
673
+ headers: { 'Authorization': `Bearer ${currentToken}` }
674
+ });
675
+
676
+ if (response.ok) {
677
+ loadHistory();
678
+ loadGallery();
679
+ } else {
680
+ const error = await response.json();
681
+ alert(error.error);
682
+ }
683
+ } catch (error) {
684
+ alert('Failed to delete image');
685
+ }
686
+ }
687
+
688
+ function closePreviewModal() {
689
+ document.getElementById('previewModal').classList.add('hidden');
690
+ }
691
+
692
+ // Event Listeners
693
+ document.addEventListener('DOMContentLoaded', () => {
694
+ checkAuth();
695
+ document.getElementById('loginForm').addEventListener('submit', login);
696
+ document.getElementById('registerForm').addEventListener('submit', register);
697
+ });
698
+
699
+ // Close modals on outside click
700
+ document.getElementById('authModal').addEventListener('click', (e) => {
701
+ if (e.target === e.currentTarget) closeAuthModal();
702
+ });
703
+
704
+ document.getElementById('previewModal').addEventListener('click', (e) => {
705
+ if (e.target === e.currentTarget) closePreviewModal();
706
+ });
707
+ </script>
708
+ </body>
709
+ </html>