ParthSadaria commited on
Commit
990be86
·
verified ·
1 Parent(s): a0b3c15

Upload SPOILER_v1.html

Browse files
Files changed (1) hide show
  1. SPOILER_v1.html +777 -0
SPOILER_v1.html ADDED
@@ -0,0 +1,777 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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>Office Procedure Expert System</title>
7
+ <style>
8
+ :root {
9
+ --primary: #1a3a6b;
10
+ --secondary: #3498db;
11
+ --accent: #f39c12;
12
+ --background: #f5f7fa;
13
+ --text: #2c3e50;
14
+ --light: #ecf0f1;
15
+ --success: #2ecc71;
16
+ --danger: #e74c3c;
17
+ }
18
+
19
+ * {
20
+ margin: 0;
21
+ padding: 0;
22
+ box-sizing: border-box;
23
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
24
+ }
25
+
26
+ body {
27
+ background-color: var(--background);
28
+ color: var(--text);
29
+ display: flex;
30
+ flex-direction: column;
31
+ min-height: 100vh;
32
+ }
33
+
34
+ header {
35
+ background-color: var(--primary);
36
+ color: white;
37
+ padding: 1rem;
38
+ text-align: center;
39
+ box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
40
+ }
41
+
42
+ h1 {
43
+ margin-bottom: 0.5rem;
44
+ }
45
+
46
+ main {
47
+ display: flex;
48
+ flex-direction: column;
49
+ flex: 1;
50
+ padding: 1rem;
51
+ max-width: 1200px;
52
+ margin: 0 auto;
53
+ width: 100%;
54
+ }
55
+
56
+ @media (min-width: 768px) {
57
+ main {
58
+ flex-direction: row;
59
+ gap: 1rem;
60
+ }
61
+ }
62
+
63
+ .chat-container {
64
+ flex: 2;
65
+ display: flex;
66
+ flex-direction: column;
67
+ background: white;
68
+ border-radius: 8px;
69
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
70
+ overflow: hidden;
71
+ margin-bottom: 1rem;
72
+ }
73
+
74
+ .rules-container {
75
+ flex: 1;
76
+ background: white;
77
+ border-radius: 8px;
78
+ box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
79
+ padding: 1rem;
80
+ display: flex;
81
+ flex-direction: column;
82
+ max-height: 85vh;
83
+ overflow: hidden;
84
+ }
85
+
86
+ .rules-header {
87
+ display: flex;
88
+ justify-content: space-between;
89
+ align-items: center;
90
+ margin-bottom: 1rem;
91
+ padding-bottom: 0.5rem;
92
+ border-bottom: 1px solid var(--light);
93
+ }
94
+
95
+ .chat-header {
96
+ background-color: var(--primary);
97
+ color: white;
98
+ padding: 1rem;
99
+ display: flex;
100
+ justify-content: space-between;
101
+ align-items: center;
102
+ }
103
+
104
+ .chat-messages {
105
+ flex: 1;
106
+ padding: 1rem;
107
+ overflow-y: auto;
108
+ display: flex;
109
+ flex-direction: column;
110
+ gap: 1rem;
111
+ max-height: 60vh;
112
+ }
113
+
114
+ .message {
115
+ max-width: 80%;
116
+ padding: 0.8rem 1rem;
117
+ border-radius: 1rem;
118
+ margin-bottom: 0.5rem;
119
+ box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
120
+ position: relative;
121
+ word-wrap: break-word;
122
+ }
123
+
124
+ .user-message {
125
+ background-color: var(--secondary);
126
+ color: white;
127
+ align-self: flex-end;
128
+ border-bottom-right-radius: 0.2rem;
129
+ }
130
+
131
+ .bot-message {
132
+ background-color: var(--light);
133
+ color: var(--text);
134
+ align-self: flex-start;
135
+ border-bottom-left-radius: 0.2rem;
136
+ }
137
+
138
+ .chat-input {
139
+ display: flex;
140
+ padding: 1rem;
141
+ border-top: 1px solid var(--light);
142
+ background-color: white;
143
+ }
144
+
145
+ .chat-input input {
146
+ flex: 1;
147
+ padding: 0.8rem 1rem;
148
+ border: 1px solid var(--light);
149
+ border-radius: 2rem;
150
+ margin-right: 0.5rem;
151
+ outline: none;
152
+ }
153
+
154
+ .chat-input input:focus {
155
+ border-color: var(--secondary);
156
+ }
157
+
158
+ button {
159
+ padding: 0.5rem 1rem;
160
+ background-color: var(--secondary);
161
+ color: white;
162
+ border: none;
163
+ border-radius: 4px;
164
+ cursor: pointer;
165
+ transition: all 0.2s;
166
+ }
167
+
168
+ button:hover {
169
+ background-color: var(--primary);
170
+ }
171
+
172
+ button.danger {
173
+ background-color: var(--danger);
174
+ }
175
+
176
+ button.success {
177
+ background-color: var(--success);
178
+ }
179
+
180
+ .rule-form {
181
+ display: flex;
182
+ flex-direction: column;
183
+ gap: 0.5rem;
184
+ margin-bottom: 1rem;
185
+ }
186
+
187
+ .rule-form textarea {
188
+ padding: 0.5rem;
189
+ border: 1px solid var(--light);
190
+ border-radius: 4px;
191
+ resize: vertical;
192
+ min-height: 80px;
193
+ font-size: 0.9rem;
194
+ margin-bottom: 0.5rem;
195
+ }
196
+
197
+ .rule-actions {
198
+ display: flex;
199
+ gap: 0.5rem;
200
+ }
201
+
202
+ .rules-list {
203
+ overflow-y: auto;
204
+ flex: 1;
205
+ }
206
+
207
+ .rule-item {
208
+ padding: 0.8rem;
209
+ border: 1px solid var(--light);
210
+ border-radius: 4px;
211
+ margin-bottom: 0.5rem;
212
+ position: relative;
213
+ }
214
+
215
+ .rule-item p {
216
+ margin-bottom: 0.5rem;
217
+ word-wrap: break-word;
218
+ }
219
+
220
+ .rule-actions-inline {
221
+ display: flex;
222
+ justify-content: flex-end;
223
+ gap: 0.5rem;
224
+ }
225
+
226
+ .language-selector {
227
+ padding: 0.5rem;
228
+ border-radius: 4px;
229
+ border: 1px solid var(--light);
230
+ background-color: white;
231
+ margin-left: 0.5rem;
232
+ }
233
+
234
+ .system-message {
235
+ text-align: center;
236
+ color: var(--text);
237
+ opacity: 0.7;
238
+ margin: 0.5rem 0;
239
+ font-size: 0.8rem;
240
+ }
241
+
242
+ .loader {
243
+ display: inline-block;
244
+ width: 20px;
245
+ height: 20px;
246
+ border: 3px solid rgba(255, 255, 255, 0.3);
247
+ border-radius: 50%;
248
+ border-top-color: white;
249
+ animation: spin 1s ease-in-out infinite;
250
+ margin-right: 0.5rem;
251
+ }
252
+
253
+ @keyframes spin {
254
+ to { transform: rotate(360deg); }
255
+ }
256
+
257
+ .hidden {
258
+ display: none;
259
+ }
260
+
261
+ .settings-btn {
262
+ background: none;
263
+ border: none;
264
+ color: white;
265
+ font-size: 1.2rem;
266
+ cursor: pointer;
267
+ }
268
+
269
+ .settings-panel {
270
+ position: absolute;
271
+ top: 60px;
272
+ right: 20px;
273
+ background: white;
274
+ border-radius: 8px;
275
+ box-shadow: 0 2px 15px rgba(0, 0, 0, 0.2);
276
+ padding: 1rem;
277
+ z-index: 100;
278
+ width: 300px;
279
+ }
280
+
281
+ .settings-header {
282
+ display: flex;
283
+ justify-content: space-between;
284
+ align-items: center;
285
+ margin-bottom: 1rem;
286
+ padding-bottom: 0.5rem;
287
+ border-bottom: 1px solid var(--light);
288
+ }
289
+
290
+ .close-btn {
291
+ background: none;
292
+ border: none;
293
+ font-size: 1.2rem;
294
+ cursor: pointer;
295
+ color: var(--text);
296
+ }
297
+
298
+ .settings-body {
299
+ display: flex;
300
+ flex-direction: column;
301
+ gap: 1rem;
302
+ }
303
+
304
+ .setting-item {
305
+ display: flex;
306
+ flex-direction: column;
307
+ gap: 0.5rem;
308
+ }
309
+
310
+ .setting-item label {
311
+ font-weight: bold;
312
+ }
313
+
314
+ .tooltip {
315
+ position: relative;
316
+ display: inline-block;
317
+ margin-left: 0.5rem;
318
+ cursor: help;
319
+ }
320
+
321
+ .tooltip .tooltiptext {
322
+ visibility: hidden;
323
+ width: 200px;
324
+ background-color: var(--text);
325
+ color: white;
326
+ text-align: center;
327
+ border-radius: 6px;
328
+ padding: 0.5rem;
329
+ position: absolute;
330
+ z-index: 1;
331
+ bottom: 125%;
332
+ left: 50%;
333
+ transform: translateX(-50%);
334
+ opacity: 0;
335
+ transition: opacity 0.3s;
336
+ font-size: 0.8rem;
337
+ }
338
+
339
+ .tooltip:hover .tooltiptext {
340
+ visibility: visible;
341
+ opacity: 1;
342
+ }
343
+ </style>
344
+ </head>
345
+ <body>
346
+ <header>
347
+ <h1>Office Procedure Expert System</h1>
348
+ <p>General Administration Department</p>
349
+ </header>
350
+
351
+ <main>
352
+ <div class="chat-container">
353
+ <div class="chat-header">
354
+ <div>
355
+ <h2>Office Procedure Assistant</h2>
356
+ </div>
357
+ <div class="chat-controls">
358
+ <select id="language-selector" class="language-selector">
359
+ <option value="en">English</option>
360
+ <option value="gu">Gujarati</option>
361
+ <option value="hi">Hindi</option>
362
+ </select>
363
+ <button id="settings-btn" class="settings-btn">⚙️</button>
364
+ </div>
365
+ </div>
366
+
367
+ <div class="chat-messages" id="chat-messages">
368
+ <div class="message bot-message">
369
+ Hello! I'm your Office Procedure Assistant. Ask me any questions about office procedures and rules, and I'll help you find the information you need.
370
+ </div>
371
+ <div class="system-message">
372
+ Add rules in the panel to the right to customize my knowledge base.
373
+ </div>
374
+ </div>
375
+
376
+ <div class="chat-input">
377
+ <input type="text" id="user-input" placeholder="Type your question here...">
378
+ <button id="send-btn">
379
+ <span id="loader" class="loader hidden"></span>
380
+ <span id="send-text">Send</span>
381
+ </button>
382
+ </div>
383
+ </div>
384
+
385
+ <div class="rules-container">
386
+ <div class="rules-header">
387
+ <h2>Knowledge Base</h2>
388
+ <button id="export-rules">Export</button>
389
+ </div>
390
+
391
+ <div class="rule-form">
392
+ <textarea id="rule-content" placeholder="Enter a rule or procedure here..."></textarea>
393
+ <div class="rule-actions">
394
+ <button id="add-rule" class="success">Add Rule</button>
395
+ <button id="clear-form">Clear</button>
396
+ </div>
397
+ </div>
398
+
399
+ <div class="rules-list" id="rules-list">
400
+ <!-- Rules will be added here dynamically -->
401
+ </div>
402
+ </div>
403
+ </main>
404
+
405
+ <div id="settings-panel" class="settings-panel hidden">
406
+ <div class="settings-header">
407
+ <h3>Settings</h3>
408
+ <button id="close-settings" class="close-btn">×</button>
409
+ </div>
410
+ <div class="settings-body">
411
+ <div class="setting-item">
412
+ <label for="api-endpoint">
413
+ API Endpoint
414
+ <div class="tooltip">ℹ️
415
+ <span class="tooltiptext">The base URL for the AI model API</span>
416
+ </div>
417
+ </label>
418
+ <input type="text" id="api-endpoint" value="https://parthsadaria-lokiai.hf.space/chat/completions">
419
+ </div>
420
+ <div class="setting-item">
421
+ <label for="api-model">
422
+ Model
423
+ <div class="tooltip">ℹ️
424
+ <span class="tooltiptext">The model to use for generating responses</span>
425
+ </div>
426
+ </label>
427
+ <input type="text" id="api-model" value="gemini">
428
+ </div>
429
+ <div class="setting-item">
430
+ <label for="api-key">
431
+ Authorization Key
432
+ <div class="tooltip">ℹ️
433
+ <span class="tooltiptext">The authorization key for API access</span>
434
+ </div>
435
+ </label>
436
+ <input type="password" id="api-key" value="sigma">
437
+ </div>
438
+ <button id="save-settings" class="success">Save Settings</button>
439
+ </div>
440
+ </div>
441
+
442
+ <script>
443
+ // Initialize the app when the DOM is fully loaded
444
+ document.addEventListener('DOMContentLoaded', function() {
445
+ // DOM Elements
446
+ const chatMessages = document.getElementById('chat-messages');
447
+ const userInput = document.getElementById('user-input');
448
+ const sendBtn = document.getElementById('send-btn');
449
+ const loader = document.getElementById('loader');
450
+ const sendText = document.getElementById('send-text');
451
+ const ruleContent = document.getElementById('rule-content');
452
+ const addRuleBtn = document.getElementById('add-rule');
453
+ const clearFormBtn = document.getElementById('clear-form');
454
+ const rulesList = document.getElementById('rules-list');
455
+ const exportRulesBtn = document.getElementById('export-rules');
456
+ const languageSelector = document.getElementById('language-selector');
457
+ const settingsBtn = document.getElementById('settings-btn');
458
+ const settingsPanel = document.getElementById('settings-panel');
459
+ const closeSettingsBtn = document.getElementById('close-settings');
460
+ const saveSettingsBtn = document.getElementById('save-settings');
461
+ const apiEndpointInput = document.getElementById('api-endpoint');
462
+ const apiModelInput = document.getElementById('api-model');
463
+ const apiKeyInput = document.getElementById('api-key');
464
+
465
+ // App State
466
+ let rules = [];
467
+ let settings = {
468
+ apiEndpoint: "https://parthsadaria-lokiai.hf.space/chat/completions",
469
+ model: "gemini",
470
+ apiKey: "sigma"
471
+ };
472
+
473
+ // Load rules from localStorage if available
474
+ function loadRules() {
475
+ const savedRules = localStorage.getItem('chatbotRules');
476
+ if (savedRules) {
477
+ rules = JSON.parse(savedRules);
478
+ renderRules();
479
+ }
480
+ }
481
+
482
+ // Load settings from localStorage if available
483
+ function loadSettings() {
484
+ const savedSettings = localStorage.getItem('chatbotSettings');
485
+ if (savedSettings) {
486
+ settings = JSON.parse(savedSettings);
487
+ apiEndpointInput.value = settings.apiEndpoint;
488
+ apiModelInput.value = settings.model;
489
+ apiKeyInput.value = settings.apiKey;
490
+ }
491
+ }
492
+
493
+ // Save rules to localStorage
494
+ function saveRules() {
495
+ localStorage.setItem('chatbotRules', JSON.stringify(rules));
496
+ }
497
+
498
+ // Save settings to localStorage
499
+ function saveSettings() {
500
+ settings = {
501
+ apiEndpoint: apiEndpointInput.value,
502
+ model: apiModelInput.value,
503
+ apiKey: apiKeyInput.value
504
+ };
505
+ localStorage.setItem('chatbotSettings', JSON.stringify(settings));
506
+ settingsPanel.classList.add('hidden');
507
+ }
508
+
509
+ // Render rules in the list
510
+ function renderRules() {
511
+ rulesList.innerHTML = '';
512
+ if (rules.length === 0) {
513
+ rulesList.innerHTML = '<div class="system-message">No rules added yet. Add rules to customize the chatbot.</div>';
514
+ return;
515
+ }
516
+
517
+ rules.forEach((rule, index) => {
518
+ const ruleElement = document.createElement('div');
519
+ ruleElement.className = 'rule-item';
520
+ ruleElement.innerHTML = `
521
+ <p>${rule}</p>
522
+ <div class="rule-actions-inline">
523
+ <button class="edit-rule" data-index="${index}">Edit</button>
524
+ <button class="delete-rule danger" data-index="${index}">Delete</button>
525
+ </div>
526
+ `;
527
+ rulesList.appendChild(ruleElement);
528
+ });
529
+
530
+ // Add event listeners to edit and delete buttons
531
+ document.querySelectorAll('.edit-rule').forEach(btn => {
532
+ btn.addEventListener('click', function() {
533
+ const index = parseInt(this.getAttribute('data-index'));
534
+ ruleContent.value = rules[index];
535
+ // Store the index to know which rule to update
536
+ ruleContent.setAttribute('data-edit-index', index);
537
+ addRuleBtn.textContent = 'Update Rule';
538
+ });
539
+ });
540
+
541
+ document.querySelectorAll('.delete-rule').forEach(btn => {
542
+ btn.addEventListener('click', function() {
543
+ const index = parseInt(this.getAttribute('data-index'));
544
+ if (confirm('Are you sure you want to delete this rule?')) {
545
+ rules.splice(index, 1);
546
+ saveRules();
547
+ renderRules();
548
+ }
549
+ });
550
+ });
551
+ }
552
+
553
+ // Add a new message to the chat
554
+ function addMessage(message, isUser = false) {
555
+ const messageElement = document.createElement('div');
556
+ messageElement.className = `message ${isUser ? 'user-message' : 'bot-message'}`;
557
+ messageElement.textContent = message;
558
+ chatMessages.appendChild(messageElement);
559
+ chatMessages.scrollTop = chatMessages.scrollHeight;
560
+ }
561
+
562
+ // Add a system message to the chat
563
+ function addSystemMessage(message) {
564
+ const messageElement = document.createElement('div');
565
+ messageElement.className = 'system-message';
566
+ messageElement.textContent = message;
567
+ chatMessages.appendChild(messageElement);
568
+ chatMessages.scrollTop = chatMessages.scrollHeight;
569
+ }
570
+
571
+ // Show loading state
572
+ function setLoading(isLoading) {
573
+ if (isLoading) {
574
+ loader.classList.remove('hidden');
575
+ sendText.textContent = 'Sending...';
576
+ sendBtn.disabled = true;
577
+ userInput.disabled = true;
578
+ } else {
579
+ loader.classList.add('hidden');
580
+ sendText.textContent = 'Send';
581
+ sendBtn.disabled = false;
582
+ userInput.disabled = false;
583
+ }
584
+ }
585
+
586
+ // Send a message to the AI API
587
+ async function sendToAI(message) {
588
+ try {
589
+ const currentLanguage = languageSelector.value;
590
+
591
+ // Create a prompt that includes rules and language preferences
592
+ let prompt = `You are an AI assistant for the General Administration Department, specializing in office procedures and rules.
593
+ The user is asking in ${currentLanguage === 'en' ? 'English' : currentLanguage === 'gu' ? 'Gujarati' : 'Hindi'}.
594
+ Please respond in ${currentLanguage === 'en' ? 'English' : currentLanguage === 'gu' ? 'Gujarati' : 'Hindi'}.
595
+
596
+ Here are the specific rules and procedures you should know about:\n\n`;
597
+
598
+ // Add each rule to the prompt
599
+ rules.forEach((rule, index) => {
600
+ prompt += `Rule ${index + 1}: ${rule}\n\n`;
601
+ });
602
+
603
+ // Add the user's message
604
+ prompt += `\nUser query: ${message}\n\nProvide a helpful, accurate response based on the rules above. If the query is not covered by these rules, politely state that you don't have that specific information.`;
605
+
606
+ // Create the API request payload
607
+ const payload = {
608
+ model: settings.model,
609
+ messages: [
610
+ {
611
+ role: "system",
612
+ content: prompt
613
+ },
614
+ {
615
+ role: "user",
616
+ content: message
617
+ }
618
+ ],
619
+ temperature: 0.5,
620
+ max_tokens: 500
621
+ };
622
+
623
+ // Make the API request
624
+ const response = await fetch(settings.apiEndpoint, {
625
+ method: 'POST',
626
+ headers: {
627
+ 'Content-Type': 'application/json',
628
+ 'Authorization': `Bearer ${settings.apiKey}`
629
+ },
630
+ body: JSON.stringify(payload)
631
+ });
632
+
633
+ if (!response.ok) {
634
+ throw new Error(`API request failed with status ${response.status}`);
635
+ }
636
+
637
+ const data = await response.json();
638
+ return data.choices[0].message.content;
639
+ } catch (error) {
640
+ console.error('Error sending message to AI:', error);
641
+ return "I'm sorry, I encountered an error while processing your request. Please try again later.";
642
+ }
643
+ }
644
+
645
+ // Handle user sending a message
646
+ async function handleSendMessage() {
647
+ const message = userInput.value.trim();
648
+ if (!message) return;
649
+
650
+ // Add user message to chat
651
+ addMessage(message, true);
652
+ userInput.value = '';
653
+
654
+ // If no rules are added, show a message
655
+ if (rules.length === 0) {
656
+ addSystemMessage("No rules have been added yet. The assistant may not provide accurate information.");
657
+ }
658
+
659
+ // Show loading indicator
660
+ setLoading(true);
661
+
662
+ // Get AI response
663
+ const response = await sendToAI(message);
664
+
665
+ // Hide loading indicator
666
+ setLoading(false);
667
+
668
+ // Add AI response to chat
669
+ addMessage(response);
670
+ }
671
+
672
+ // Handle adding or updating a rule
673
+ function handleAddRule() {
674
+ const content = ruleContent.value.trim();
675
+ if (!content) return;
676
+
677
+ const editIndex = ruleContent.getAttribute('data-edit-index');
678
+
679
+ if (editIndex !== null) {
680
+ // Update existing rule
681
+ rules[editIndex] = content;
682
+ ruleContent.removeAttribute('data-edit-index');
683
+ addRuleBtn.textContent = 'Add Rule';
684
+ } else {
685
+ // Add new rule
686
+ rules.push(content);
687
+ }
688
+
689
+ saveRules();
690
+ renderRules();
691
+ ruleContent.value = '';
692
+ }
693
+
694
+ // Export rules to a JSON file
695
+ function exportRules() {
696
+ const dataStr = JSON.stringify(rules, null, 2);
697
+ const dataUri = 'data:application/json;charset=utf-8,'+ encodeURIComponent(dataStr);
698
+
699
+ const exportFileDefaultName = 'chatbot-rules.json';
700
+
701
+ const linkElement = document.createElement('a');
702
+ linkElement.setAttribute('href', dataUri);
703
+ linkElement.setAttribute('download', exportFileDefaultName);
704
+ linkElement.click();
705
+ }
706
+
707
+ // Event Listeners
708
+ sendBtn.addEventListener('click', handleSendMessage);
709
+
710
+ userInput.addEventListener('keypress', function(e) {
711
+ if (e.key === 'Enter') {
712
+ handleSendMessage();
713
+ }
714
+ });
715
+
716
+ addRuleBtn.addEventListener('click', handleAddRule);
717
+
718
+ clearFormBtn.addEventListener('click', function() {
719
+ ruleContent.value = '';
720
+ ruleContent.removeAttribute('data-edit-index');
721
+ addRuleBtn.textContent = 'Add Rule';
722
+ });
723
+
724
+ exportRulesBtn.addEventListener('click', exportRules);
725
+
726
+ settingsBtn.addEventListener('click', function() {
727
+ settingsPanel.classList.toggle('hidden');
728
+ });
729
+
730
+ closeSettingsBtn.addEventListener('click', function() {
731
+ settingsPanel.classList.add('hidden');
732
+ });
733
+
734
+ saveSettingsBtn.addEventListener('click', saveSettings);
735
+
736
+ // Import rules functionality
737
+ document.addEventListener('dragover', function(e) {
738
+ e.preventDefault();
739
+ e.stopPropagation();
740
+ });
741
+
742
+ document.addEventListener('drop', function(e) {
743
+ e.preventDefault();
744
+ e.stopPropagation();
745
+
746
+ const file = e.dataTransfer.files[0];
747
+ if (file && file.type === 'application/json') {
748
+ const reader = new FileReader();
749
+ reader.onload = function(event) {
750
+ try {
751
+ const importedRules = JSON.parse(event.target.result);
752
+ if (Array.isArray(importedRules)) {
753
+ if (confirm(`Import ${importedRules.length} rules? This will replace existing rules.`)) {
754
+ rules = importedRules;
755
+ saveRules();
756
+ renderRules();
757
+ addSystemMessage(`Successfully imported ${importedRules.length} rules.`);
758
+ }
759
+ }
760
+ } catch (error) {
761
+ console.error('Error parsing JSON file:', error);
762
+ addSystemMessage('Error importing rules. Make sure the file is a valid JSON array.');
763
+ }
764
+ };
765
+ reader.readAsText(file);
766
+ } else {
767
+ addSystemMessage('Please drop a valid JSON file.');
768
+ }
769
+ });
770
+
771
+ // Initialize the app
772
+ loadSettings();
773
+ loadRules();
774
+ });
775
+ </script>
776
+ </body>
777
+ </html>