VISHAL18for4 commited on
Commit
f8c9b84
Β·
verified Β·
1 Parent(s): 9ad52d5

Create Admin.html

Browse files
Files changed (1) hide show
  1. public/Admin.html +253 -0
public/Admin.html ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Admin Gallery Β· Snapshots</title>
7
+ <style>
8
+ * { margin: 0; padding: 0; box-sizing: border-box; }
9
+ body {
10
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
11
+ background: #0d0d1a;
12
+ color: #eee;
13
+ padding: 20px;
14
+ min-height: 100vh;
15
+ }
16
+ .login-container {
17
+ max-width: 400px;
18
+ margin: 100px auto;
19
+ background: #1a1a40;
20
+ padding: 40px;
21
+ border-radius: 16px;
22
+ border: 1px solid #533483;
23
+ text-align: center;
24
+ }
25
+ .login-container h1 { margin-bottom: 20px; color: #f5a623; }
26
+ .login-container input {
27
+ width: 100%;
28
+ padding: 12px;
29
+ margin: 10px 0;
30
+ border: 1px solid #533483;
31
+ border-radius: 8px;
32
+ background: #0d0d1a;
33
+ color: #fff;
34
+ font-size: 1rem;
35
+ }
36
+ .login-container button {
37
+ width: 100%;
38
+ padding: 12px;
39
+ background: #e94560;
40
+ border: none;
41
+ border-radius: 8px;
42
+ color: #fff;
43
+ font-size: 1.1rem;
44
+ cursor: pointer;
45
+ transition: 0.2s;
46
+ }
47
+ .login-container button:hover { background: #c73652; }
48
+ .error { color: #ff4444; margin-top: 10px; }
49
+
50
+ .gallery {
51
+ display: none;
52
+ max-width: 1400px;
53
+ margin: 0 auto;
54
+ }
55
+ .gallery-header {
56
+ display: flex;
57
+ justify-content: space-between;
58
+ align-items: center;
59
+ padding: 10px 0 20px;
60
+ border-bottom: 1px solid #533483;
61
+ margin-bottom: 20px;
62
+ flex-wrap: wrap;
63
+ gap: 10px;
64
+ }
65
+ .gallery-header h1 { color: #f5a623; }
66
+ .gallery-header .badge {
67
+ background: #533483;
68
+ padding: 6px 16px;
69
+ border-radius: 20px;
70
+ font-size: 0.9rem;
71
+ }
72
+ .gallery-grid {
73
+ display: grid;
74
+ grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
75
+ gap: 20px;
76
+ }
77
+ .gallery-item {
78
+ background: #1a1a40;
79
+ border-radius: 12px;
80
+ overflow: hidden;
81
+ border: 1px solid #2a2a5a;
82
+ transition: 0.3s;
83
+ }
84
+ .gallery-item:hover { transform: scale(1.02); border-color: #e94560; }
85
+ .gallery-item img {
86
+ width: 100%;
87
+ height: 200px;
88
+ object-fit: cover;
89
+ display: block;
90
+ }
91
+ .gallery-item .info {
92
+ padding: 10px 14px;
93
+ font-size: 0.8rem;
94
+ color: #aaa;
95
+ display: flex;
96
+ justify-content: space-between;
97
+ align-items: center;
98
+ }
99
+ .gallery-item .info a {
100
+ color: #f5a623;
101
+ text-decoration: none;
102
+ font-weight: bold;
103
+ }
104
+ .gallery-item .info a:hover { text-decoration: underline; }
105
+ .empty-msg {
106
+ grid-column: 1 / -1;
107
+ text-align: center;
108
+ padding: 60px;
109
+ color: #666;
110
+ font-size: 1.2rem;
111
+ }
112
+ .refresh-btn {
113
+ background: #533483;
114
+ border: none;
115
+ color: #fff;
116
+ padding: 8px 20px;
117
+ border-radius: 8px;
118
+ cursor: pointer;
119
+ transition: 0.2s;
120
+ }
121
+ .refresh-btn:hover { background: #6a4a9a; }
122
+ .logout-btn {
123
+ background: #333;
124
+ border: none;
125
+ color: #fff;
126
+ padding: 8px 20px;
127
+ border-radius: 8px;
128
+ cursor: pointer;
129
+ }
130
+ .logout-btn:hover { background: #555; }
131
+ </style>
132
+ </head>
133
+ <body>
134
+
135
+ <!-- Login Screen -->
136
+ <div id="loginScreen" class="login-container">
137
+ <h1>πŸ” Admin Gallery</h1>
138
+ <p style="color:#aaa; margin-bottom:20px;">Enter password to view snapshots</p>
139
+ <input type="password" id="passwordInput" placeholder="Enter password" />
140
+ <button id="loginBtn">Unlock Gallery</button>
141
+ <div id="loginError" class="error"></div>
142
+ </div>
143
+
144
+ <!-- Gallery -->
145
+ <div id="galleryScreen" class="gallery">
146
+ <div class="gallery-header">
147
+ <h1>πŸ“Έ Saved Snapshots</h1>
148
+ <div>
149
+ <span class="badge" id="countBadge">0 images</span>
150
+ <button class="refresh-btn" id="refreshBtn">⟳ Refresh</button>
151
+ <button class="logout-btn" id="logoutBtn">πŸšͺ Logout</button>
152
+ </div>
153
+ </div>
154
+ <div class="gallery-grid" id="galleryGrid">
155
+ <div class="empty-msg">Loading snapshots...</div>
156
+ </div>
157
+ </div>
158
+
159
+ <script>
160
+ const PASSWORD = '26jan24march';
161
+ const loginScreen = document.getElementById('loginScreen');
162
+ const galleryScreen = document.getElementById('galleryScreen');
163
+ const passwordInput = document.getElementById('passwordInput');
164
+ const loginBtn = document.getElementById('loginBtn');
165
+ const loginError = document.getElementById('loginError');
166
+ const galleryGrid = document.getElementById('galleryGrid');
167
+ const countBadge = document.getElementById('countBadge');
168
+ const refreshBtn = document.getElementById('refreshBtn');
169
+ const logoutBtn = document.getElementById('logoutBtn');
170
+
171
+ // Check if already logged in (sessionStorage)
172
+ if (sessionStorage.getItem('adminLoggedIn') === 'true') {
173
+ loginScreen.style.display = 'none';
174
+ galleryScreen.style.display = 'block';
175
+ loadSnapshots();
176
+ }
177
+
178
+ loginBtn.addEventListener('click', () => {
179
+ const pass = passwordInput.value.trim();
180
+ if (pass === PASSWORD) {
181
+ sessionStorage.setItem('adminLoggedIn', 'true');
182
+ loginScreen.style.display = 'none';
183
+ galleryScreen.style.display = 'block';
184
+ loginError.textContent = '';
185
+ loadSnapshots();
186
+ } else {
187
+ loginError.textContent = '❌ Incorrect password. Try again.';
188
+ passwordInput.value = '';
189
+ passwordInput.focus();
190
+ }
191
+ });
192
+
193
+ // Enter key on password field
194
+ passwordInput.addEventListener('keydown', (e) => {
195
+ if (e.key === 'Enter') loginBtn.click();
196
+ });
197
+
198
+ logoutBtn.addEventListener('click', () => {
199
+ sessionStorage.removeItem('adminLoggedIn');
200
+ galleryScreen.style.display = 'none';
201
+ loginScreen.style.display = 'block';
202
+ passwordInput.value = '';
203
+ loginError.textContent = '';
204
+ });
205
+
206
+ refreshBtn.addEventListener('click', loadSnapshots);
207
+
208
+ async function loadSnapshots() {
209
+ galleryGrid.innerHTML = '<div class="empty-msg">Loading snapshots...</div>';
210
+ try {
211
+ const response = await fetch('/api/snapshots/list');
212
+ const data = await response.json();
213
+
214
+ if (!data.success || !data.files || data.files.length === 0) {
215
+ galleryGrid.innerHTML = '<div class="empty-msg">πŸ“­ No snapshots saved yet. Draw something and save!</div>';
216
+ countBadge.textContent = '0 images';
217
+ return;
218
+ }
219
+
220
+ // Sort files by name (newest first)
221
+ const files = data.files.sort().reverse();
222
+ countBadge.textContent = `${files.length} images`;
223
+
224
+ let html = '';
225
+ files.forEach(filename => {
226
+ const imageUrl = `/snapshots/${filename}`;
227
+ html += `
228
+ <div class="gallery-item">
229
+ <img src="${imageUrl}" alt="${filename}" loading="lazy"
230
+ onerror="this.src='data:image/svg+xml,%3Csvg xmlns=%22http://www.w3.org/2000/svg%22 width=%22250%22 height=%22200%22%3E%3Crect fill=%22%23333%22 width=%22250%22 height=%22200%22/%3E%3Ctext x=%2250%22 y=%22100%22 fill=%22%23666%22 font-family=%22sans-serif%22 font-size=%2214%22%3EImage not found%3C/text%3E%3C/svg%3E'" />
231
+ <div class="info">
232
+ <span>${filename}</span>
233
+ <a href="${imageUrl}" target="_blank">πŸ”— View</a>
234
+ </div>
235
+ </div>
236
+ `;
237
+ });
238
+ galleryGrid.innerHTML = html;
239
+ } catch (err) {
240
+ console.error('[Admin] Load error:', err);
241
+ galleryGrid.innerHTML = '<div class="empty-msg">❌ Error loading snapshots. Is the server running?</div>';
242
+ }
243
+ }
244
+
245
+ // Auto-refresh every 30 seconds
246
+ setInterval(() => {
247
+ if (sessionStorage.getItem('adminLoggedIn') === 'true') {
248
+ loadSnapshots();
249
+ }
250
+ }, 30000);
251
+ </script>
252
+ </body>
253
+ </html>