Phoenix21 commited on
Commit
4efa4a2
·
verified ·
1 Parent(s): 5a44b8b

Create static/index.html

Browse files
Files changed (1) hide show
  1. src/main/resources/static/index.html +499 -0
src/main/resources/static/index.html ADDED
@@ -0,0 +1,499 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Gemini Chat - Test UI</title>
7
+ <style>
8
+ * {
9
+ margin: 0;
10
+ padding: 0;
11
+ box-sizing: border-box;
12
+ }
13
+
14
+ body {
15
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
16
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
17
+ height: 100vh;
18
+ display: flex;
19
+ justify-content: center;
20
+ align-items: center;
21
+ }
22
+
23
+ .chat-container {
24
+ background: white;
25
+ border-radius: 20px;
26
+ box-shadow: 0 20px 40px rgba(0,0,0,0.1);
27
+ width: 90%;
28
+ max-width: 800px;
29
+ height: 600px;
30
+ display: flex;
31
+ flex-direction: column;
32
+ overflow: hidden;
33
+ }
34
+
35
+ .chat-header {
36
+ background: linear-gradient(45deg, #4CAF50, #45a049);
37
+ color: white;
38
+ padding: 20px;
39
+ text-align: center;
40
+ display: flex;
41
+ justify-content: space-between;
42
+ align-items: center;
43
+ }
44
+
45
+ .header-info {
46
+ display: flex;
47
+ flex-direction: column;
48
+ align-items: flex-start;
49
+ }
50
+
51
+ .status-indicator {
52
+ display: flex;
53
+ align-items: center;
54
+ gap: 8px;
55
+ font-size: 0.9em;
56
+ opacity: 0.9;
57
+ }
58
+
59
+ .status-dot {
60
+ width: 8px;
61
+ height: 8px;
62
+ border-radius: 50%;
63
+ background: #ff4444;
64
+ animation: pulse 2s infinite;
65
+ }
66
+
67
+ .status-dot.online {
68
+ background: #44ff44;
69
+ }
70
+
71
+ @keyframes pulse {
72
+ 0% { opacity: 1; }
73
+ 50% { opacity: 0.5; }
74
+ 100% { opacity: 1; }
75
+ }
76
+
77
+ .chat-messages {
78
+ flex: 1;
79
+ padding: 20px;
80
+ overflow-y: auto;
81
+ background: #f8f9fa;
82
+ display: flex;
83
+ flex-direction: column;
84
+ gap: 15px;
85
+ }
86
+
87
+ .message {
88
+ display: flex;
89
+ gap: 10px;
90
+ animation: slideIn 0.3s ease-out;
91
+ }
92
+
93
+ @keyframes slideIn {
94
+ from {
95
+ opacity: 0;
96
+ transform: translateY(20px);
97
+ }
98
+ to {
99
+ opacity: 1;
100
+ transform: translateY(0);
101
+ }
102
+ }
103
+
104
+ .message.user {
105
+ justify-content: flex-end;
106
+ }
107
+
108
+ .message-bubble {
109
+ max-width: 70%;
110
+ padding: 12px 18px;
111
+ border-radius: 18px;
112
+ word-wrap: break-word;
113
+ line-height: 1.4;
114
+ }
115
+
116
+ .message.user .message-bubble {
117
+ background: linear-gradient(45deg, #007bff, #0056b3);
118
+ color: white;
119
+ border-bottom-right-radius: 4px;
120
+ }
121
+
122
+ .message.bot .message-bubble {
123
+ background: white;
124
+ border: 1px solid #e0e0e0;
125
+ color: #333;
126
+ border-bottom-left-radius: 4px;
127
+ box-shadow: 0 2px 5px rgba(0,0,0,0.1);
128
+ }
129
+
130
+ .message-time {
131
+ font-size: 0.7em;
132
+ opacity: 0.7;
133
+ margin-top: 4px;
134
+ }
135
+
136
+ .typing-indicator {
137
+ display: none;
138
+ align-items: center;
139
+ gap: 10px;
140
+ padding: 15px 20px;
141
+ font-style: italic;
142
+ color: #666;
143
+ }
144
+
145
+ .typing-dots {
146
+ display: flex;
147
+ gap: 4px;
148
+ }
149
+
150
+ .typing-dot {
151
+ width: 8px;
152
+ height: 8px;
153
+ border-radius: 50%;
154
+ background: #4CAF50;
155
+ animation: typingDot 1.4s infinite ease-in-out;
156
+ }
157
+
158
+ .typing-dot:nth-child(2) { animation-delay: 0.2s; }
159
+ .typing-dot:nth-child(3) { animation-delay: 0.4s; }
160
+
161
+ @keyframes typingDot {
162
+ 0%, 60%, 100% { transform: translateY(0); }
163
+ 30% { transform: translateY(-10px); }
164
+ }
165
+
166
+ .chat-input-container {
167
+ padding: 20px;
168
+ background: white;
169
+ border-top: 1px solid #e0e0e0;
170
+ }
171
+
172
+ .chat-input-form {
173
+ display: flex;
174
+ gap: 10px;
175
+ align-items: center;
176
+ }
177
+
178
+ .chat-input {
179
+ flex: 1;
180
+ padding: 12px 18px;
181
+ border: 2px solid #e0e0e0;
182
+ border-radius: 25px;
183
+ outline: none;
184
+ font-size: 16px;
185
+ transition: border-color 0.3s;
186
+ }
187
+
188
+ .chat-input:focus {
189
+ border-color: #4CAF50;
190
+ }
191
+
192
+ .send-button {
193
+ background: linear-gradient(45deg, #4CAF50, #45a049);
194
+ color: white;
195
+ border: none;
196
+ border-radius: 50%;
197
+ width: 50px;
198
+ height: 50px;
199
+ cursor: pointer;
200
+ display: flex;
201
+ align-items: center;
202
+ justify-content: center;
203
+ transition: transform 0.2s, box-shadow 0.2s;
204
+ font-size: 20px;
205
+ }
206
+
207
+ .send-button:hover {
208
+ transform: scale(1.05);
209
+ box-shadow: 0 5px 15px rgba(76, 175, 80, 0.4);
210
+ }
211
+
212
+ .send-button:disabled {
213
+ background: #ccc;
214
+ cursor: not-allowed;
215
+ transform: none;
216
+ box-shadow: none;
217
+ }
218
+
219
+ .error-message {
220
+ background: #ffebee;
221
+ color: #c62828;
222
+ padding: 10px;
223
+ border-radius: 5px;
224
+ margin: 10px 20px;
225
+ border-left: 4px solid #f44336;
226
+ display: none;
227
+ }
228
+
229
+ .health-status {
230
+ font-size: 0.8em;
231
+ opacity: 0.8;
232
+ }
233
+
234
+ /* Responsive Design */
235
+ @media (max-width: 600px) {
236
+ .chat-container {
237
+ width: 95%;
238
+ height: 90vh;
239
+ margin: 20px;
240
+ }
241
+
242
+ .chat-header {
243
+ padding: 15px;
244
+ }
245
+
246
+ .chat-messages {
247
+ padding: 15px;
248
+ }
249
+
250
+ .message-bubble {
251
+ max-width: 85%;
252
+ }
253
+
254
+ .chat-input-container {
255
+ padding: 15px;
256
+ }
257
+ }
258
+
259
+ /* Scrollbar Styling */
260
+ .chat-messages::-webkit-scrollbar {
261
+ width: 6px;
262
+ }
263
+
264
+ .chat-messages::-webkit-scrollbar-track {
265
+ background: #f1f1f1;
266
+ border-radius: 3px;
267
+ }
268
+
269
+ .chat-messages::-webkit-scrollbar-thumb {
270
+ background: #c1c1c1;
271
+ border-radius: 3px;
272
+ }
273
+
274
+ .chat-messages::-webkit-scrollbar-thumb:hover {
275
+ background: #a8a8a8;
276
+ }
277
+ </style>
278
+ </head>
279
+ <body>
280
+ <div class="chat-container">
281
+ <div class="chat-header">
282
+ <div class="header-info">
283
+ <h2>🤖 Gemini Chat Assistant</h2>
284
+ <div class="status-indicator">
285
+ <div class="status-dot" id="statusDot"></div>
286
+ <span id="statusText">Checking connection...</span>
287
+ </div>
288
+ </div>
289
+ <div class="health-status">
290
+ <button onclick="checkHealth()" style="background: rgba(255,255,255,0.2); border: 1px solid rgba(255,255,255,0.3); color: white; padding: 5px 10px; border-radius: 15px; cursor: pointer; font-size: 0.8em;">
291
+ 🔄 Check Status
292
+ </button>
293
+ </div>
294
+ </div>
295
+
296
+ <div class="error-message" id="errorMessage"></div>
297
+
298
+ <div class="chat-messages" id="chatMessages">
299
+ <div class="message bot">
300
+ <div class="message-bubble">
301
+ 👋 Hello! I'm your Gemini-powered chat assistant. How can I help you today?
302
+ <div class="message-time" id="welcomeTime"></div>
303
+ </div>
304
+ </div>
305
+ </div>
306
+
307
+ <div class="typing-indicator" id="typingIndicator">
308
+ <span>Gemini is thinking</span>
309
+ <div class="typing-dots">
310
+ <div class="typing-dot"></div>
311
+ <div class="typing-dot"></div>
312
+ <div class="typing-dot"></div>
313
+ </div>
314
+ </div>
315
+
316
+ <div class="chat-input-container">
317
+ <form class="chat-input-form" id="chatForm">
318
+ <input
319
+ type="text"
320
+ class="chat-input"
321
+ id="messageInput"
322
+ placeholder="Type your message here..."
323
+ autocomplete="off"
324
+ maxlength="1000"
325
+ >
326
+ <button type="submit" class="send-button" id="sendButton">
327
+
328
+ </button>
329
+ </form>
330
+ </div>
331
+ </div>
332
+
333
+ <script>
334
+ // Configuration
335
+ const API_BASE_URL = 'http://localhost:8080/api/chat';
336
+
337
+ // DOM Elements
338
+ const chatMessages = document.getElementById('chatMessages');
339
+ const messageInput = document.getElementById('messageInput');
340
+ const sendButton = document.getElementById('sendButton');
341
+ const chatForm = document.getElementById('chatForm');
342
+ const typingIndicator = document.getElementById('typingIndicator');
343
+ const errorMessage = document.getElementById('errorMessage');
344
+ const statusDot = document.getElementById('statusDot');
345
+ const statusText = document.getElementById('statusText');
346
+
347
+ // Initialize
348
+ document.addEventListener('DOMContentLoaded', function() {
349
+ document.getElementById('welcomeTime').textContent = getCurrentTime();
350
+ checkHealth();
351
+ messageInput.focus();
352
+ });
353
+
354
+ // Event Listeners
355
+ chatForm.addEventListener('submit', function(e) {
356
+ e.preventDefault();
357
+ sendMessage();
358
+ });
359
+
360
+ messageInput.addEventListener('keypress', function(e) {
361
+ if (e.key === 'Enter' && !e.shiftKey) {
362
+ e.preventDefault();
363
+ sendMessage();
364
+ }
365
+ });
366
+
367
+ // Functions
368
+ function getCurrentTime() {
369
+ return new Date().toLocaleTimeString('en-US', {
370
+ hour12: true,
371
+ hour: 'numeric',
372
+ minute: '2-digit'
373
+ });
374
+ }
375
+
376
+ function showError(message) {
377
+ errorMessage.textContent = message;
378
+ errorMessage.style.display = 'block';
379
+ setTimeout(() => {
380
+ errorMessage.style.display = 'none';
381
+ }, 5000);
382
+ }
383
+
384
+ function updateStatus(online, message) {
385
+ statusDot.className = `status-dot ${online ? 'online' : ''}`;
386
+ statusText.textContent = message;
387
+ }
388
+
389
+ async function checkHealth() {
390
+ try {
391
+ const response = await fetch(`${API_BASE_URL}/health`);
392
+ if (response.ok) {
393
+ const data = await response.json();
394
+ updateStatus(true, `Connected • ${data.service}`);
395
+ } else {
396
+ updateStatus(false, 'Backend unavailable');
397
+ }
398
+ } catch (error) {
399
+ updateStatus(false, 'Connection failed');
400
+ console.error('Health check failed:', error);
401
+ }
402
+ }
403
+
404
+ function addMessage(content, isUser = false) {
405
+ const messageDiv = document.createElement('div');
406
+ messageDiv.className = `message ${isUser ? 'user' : 'bot'}`;
407
+
408
+ const bubbleDiv = document.createElement('div');
409
+ bubbleDiv.className = 'message-bubble';
410
+ bubbleDiv.innerHTML = `
411
+ ${content}
412
+ <div class="message-time">${getCurrentTime()}</div>
413
+ `;
414
+
415
+ messageDiv.appendChild(bubbleDiv);
416
+ chatMessages.appendChild(messageDiv);
417
+
418
+ // Scroll to bottom
419
+ chatMessages.scrollTop = chatMessages.scrollHeight;
420
+ }
421
+
422
+ function showTypingIndicator() {
423
+ typingIndicator.style.display = 'flex';
424
+ chatMessages.scrollTop = chatMessages.scrollHeight;
425
+ }
426
+
427
+ function hideTypingIndicator() {
428
+ typingIndicator.style.display = 'none';
429
+ }
430
+
431
+ function setLoading(loading) {
432
+ sendButton.disabled = loading;
433
+ sendButton.textContent = loading ? '⏳' : '➤';
434
+ messageInput.disabled = loading;
435
+
436
+ if (loading) {
437
+ showTypingIndicator();
438
+ } else {
439
+ hideTypingIndicator();
440
+ }
441
+ }
442
+
443
+ async function sendMessage() {
444
+ const message = messageInput.value.trim();
445
+ if (!message) return;
446
+
447
+ // Add user message
448
+ addMessage(message, true);
449
+ messageInput.value = '';
450
+ setLoading(true);
451
+
452
+ try {
453
+ const response = await fetch(`${API_BASE_URL}/message`, {
454
+ method: 'POST',
455
+ headers: {
456
+ 'Content-Type': 'application/json',
457
+ },
458
+ body: JSON.stringify({ message: message })
459
+ });
460
+
461
+ if (!response.ok) {
462
+ throw new Error(`HTTP error! status: ${response.status}`);
463
+ }
464
+
465
+ const data = await response.json();
466
+
467
+ if (data.success) {
468
+ // Format the response for better display
469
+ const formattedResponse = data.response
470
+ .replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>')
471
+ .replace(/\n/g, '<br>');
472
+
473
+ addMessage(formattedResponse, false);
474
+ } else {
475
+ throw new Error(data.error || 'Unknown error occurred');
476
+ }
477
+
478
+ } catch (error) {
479
+ console.error('Error sending message:', error);
480
+ showError(`Failed to send message: ${error.message}`);
481
+ addMessage('😔 Sorry, I encountered an error. Please try again or check if the backend is running.', false);
482
+ } finally {
483
+ setLoading(false);
484
+ messageInput.focus();
485
+ }
486
+ }
487
+
488
+ // Auto-focus input when clicking anywhere in chat area
489
+ chatMessages.addEventListener('click', () => {
490
+ if (!messageInput.disabled) {
491
+ messageInput.focus();
492
+ }
493
+ });
494
+
495
+ // Check health status periodically
496
+ setInterval(checkHealth, 30000); // Check every 30 seconds
497
+ </script>
498
+ </body>
499
+ </html>