IZERE HIRWA Roger commited on
Commit
5d9430a
·
1 Parent(s): 9d7bed2
Files changed (3) hide show
  1. app.py +21 -21
  2. chatbot/api.js +95 -0
  3. chatbot/config-ui.js +180 -398
app.py CHANGED
@@ -982,6 +982,26 @@ def style_css_asset():
982
  def app_js_asset():
983
  return send_from_directory(_CHATBOT_STATIC_DIR, 'app.js')
984
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
985
  SYSTEM_PROMPT = """You are AIMHSA (AI Mental Health Support Assistant), a professional multilingual mental health chatbot specifically designed for Rwanda. You provide culturally-sensitive, evidence-based mental health support in four languages: English, French, Kiswahili, and Kinyarwanda.
986
 
987
  ## SCOPE BOUNDARIES - CRITICAL
@@ -1676,27 +1696,7 @@ Rappelez-vous: Vous êtes un système professionnel de soutien en santé mentale
1676
 
1677
  Amabwiriza y'ubuhanga:
1678
  - Ube umuntu w'umutima mwiza, w'umutima mwiza, kandi w'umutima mwiza
1679
- - Tanga amakuru yashyizweho ku bikoresho byo mu cyerekezo mugihe cyose
1680
- - VUGURA BURI
1681
- Amabwiriza y'ubuhanga:
1682
- - Ube umuntu w'umutima mwiza, w'umutima mwiza, kandi w'umutima mwiza
1683
- - Tanga amakuru yashyizweho ku bikoresho byo mu cyerekezo mugihe cyose
1684
- - VUGURA BURI
1685
- - Gardez les réponses professionnelles, concises mais utiles
1686
- - Utilisez le contexte fourni pour donner des informations précises et pertinentes
1687
- - Maintenez un ton naturel et conversationnel en français
1688
- - Assurez des standards professionnels de soutien en santé mentale
1689
-
1690
- Rappelez-vous: Vous êtes un système professionnel de soutien en santé mentale conçu pour fournir une assistance immédiate et culturellement appropriée tout en connectant les utilisateurs aux soins professionnels quand nécessaire.""",
1691
-
1692
- 'rw': """Uri AIMHSA, umufasha w'ubuzima bw'ubwoba bw'u Rwanda w'ubuhanga.
1693
-
1694
- Amabwiriza y'ubuhanga:
1695
- - Ube umuntu w'umutima mwiza, w'umutima mwiza, kandi w'umutima mwiza
1696
- - Tanga amakuru yashyizweho ku bikoresho byo mu cyerekezo mugihe cyose
1697
- - VUGURA BURI GIHE mu Kinyarwanda GUSA - NTUVUGE mu ndimi zindi
1698
- - NTUBAZE cyangwa NTUBAZE imiti
1699
- - Gushimangira ubuvuzi bw'ubuhanga mugihe cyose
1700
  - Ku bihano, tanga umutwe wa Ligne d'assistance en santé mentale y'u Rwanda: 105
1701
  - Komeza amajwi make ariko akunze
1702
  - Koresha icyerekezo cyatanzwe kugira ngo utange amakuru y'ukuri kandi yihariye
 
982
  def app_js_asset():
983
  return send_from_directory(_CHATBOT_STATIC_DIR, 'app.js')
984
 
985
+ @app.route('/config-ui.js')
986
+ def config_ui_js_asset():
987
+ return send_from_directory(_CHATBOT_STATIC_DIR, 'config-ui.js')
988
+
989
+ @app.route('/config.js')
990
+ def config_js_asset():
991
+ return send_from_directory(_CHATBOT_STATIC_DIR, 'config.js')
992
+
993
+ @app.route('/api.js')
994
+ def api_js_asset():
995
+ return send_from_directory(_CHATBOT_STATIC_DIR, 'api.js')
996
+
997
+ @app.route('/admin_advanced.js')
998
+ def admin_advanced_js_asset():
999
+ return send_from_directory(_CHATBOT_STATIC_DIR, 'admin_advanced.js')
1000
+
1001
+ @app.route('/professional_advanced.js')
1002
+ def professional_advanced_js_asset():
1003
+ return send_from_directory(_CHATBOT_STATIC_DIR, 'professional_advanced.js')
1004
+
1005
  SYSTEM_PROMPT = """You are AIMHSA (AI Mental Health Support Assistant), a professional multilingual mental health chatbot specifically designed for Rwanda. You provide culturally-sensitive, evidence-based mental health support in four languages: English, French, Kiswahili, and Kinyarwanda.
1006
 
1007
  ## SCOPE BOUNDARIES - CRITICAL
 
1696
 
1697
  Amabwiriza y'ubuhanga:
1698
  - Ube umuntu w'umutima mwiza, w'umutima mwiza, kandi w'umutima mwiza
1699
+ - Tanga amakuru yashyizweho ku bik
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1700
  - Ku bihano, tanga umutwe wa Ligne d'assistance en santé mentale y'u Rwanda: 105
1701
  - Komeza amajwi make ariko akunze
1702
  - Koresha icyerekezo cyatanzwe kugira ngo utange amakuru y'ukuri kandi yihariye
chatbot/api.js ADDED
@@ -0,0 +1,95 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // AIMHSA API Helper
2
+ window.AIMHSA = window.AIMHSA || {};
3
+
4
+ // API helper class for making HTTP requests
5
+ class AIMHSAAPI {
6
+ constructor() {
7
+ this.baseUrl = this.getApiBaseUrl();
8
+ this.defaultHeaders = {
9
+ 'Content-Type': 'application/json'
10
+ };
11
+ }
12
+
13
+ getApiBaseUrl() {
14
+ if (window.AIMHSA && window.AIMHSA.Config) {
15
+ return window.AIMHSA.Config.getApiBaseUrl();
16
+ }
17
+ // Fallback to auto-detection
18
+ return `${window.location.protocol}//${window.location.hostname}${window.location.port ? ':' + window.location.port : ''}`;
19
+ }
20
+
21
+ async request(path, options = {}) {
22
+ const url = `${this.baseUrl}${path}`;
23
+ const config = {
24
+ method: 'GET',
25
+ headers: { ...this.defaultHeaders },
26
+ ...options
27
+ };
28
+
29
+ // Add body if provided and method supports it
30
+ if (options.body && ['POST', 'PUT', 'PATCH'].includes(config.method)) {
31
+ config.body = typeof options.body === 'string' ? options.body : JSON.stringify(options.body);
32
+ }
33
+
34
+ try {
35
+ const response = await fetch(url, config);
36
+
37
+ if (!response.ok) {
38
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
39
+ }
40
+
41
+ const contentType = response.headers.get('content-type');
42
+ if (contentType && contentType.includes('application/json')) {
43
+ return await response.json();
44
+ }
45
+
46
+ return await response.text();
47
+ } catch (error) {
48
+ console.error(`API request failed: ${config.method} ${url}`, error);
49
+ throw error;
50
+ }
51
+ }
52
+
53
+ // Convenience methods
54
+ get(path, options = {}) {
55
+ return this.request(path, { ...options, method: 'GET' });
56
+ }
57
+
58
+ post(path, body, options = {}) {
59
+ return this.request(path, { ...options, method: 'POST', body });
60
+ }
61
+
62
+ put(path, body, options = {}) {
63
+ return this.request(path, { ...options, method: 'PUT', body });
64
+ }
65
+
66
+ delete(path, options = {}) {
67
+ return this.request(path, { ...options, method: 'DELETE' });
68
+ }
69
+
70
+ // Authentication helpers
71
+ setAuthToken(token) {
72
+ this.defaultHeaders['Authorization'] = `Bearer ${token}`;
73
+ }
74
+
75
+ clearAuthToken() {
76
+ delete this.defaultHeaders['Authorization'];
77
+ }
78
+
79
+ // Professional-specific helper
80
+ setProfessionalId(professionalId) {
81
+ this.defaultHeaders['X-Professional-ID'] = professionalId;
82
+ }
83
+
84
+ clearProfessionalId() {
85
+ delete this.defaultHeaders['X-Professional-ID'];
86
+ }
87
+ }
88
+
89
+ // Initialize global API instance
90
+ window.AIMHSA.API = new AIMHSAAPI();
91
+
92
+ // Export for module systems if available
93
+ if (typeof module !== 'undefined' && module.exports) {
94
+ module.exports = AIMHSAAPI;
95
+ }
chatbot/config-ui.js CHANGED
@@ -1,419 +1,201 @@
1
  /**
2
- * Configuration UI Management
3
  * Provides UI components for managing frontend configuration
4
  */
5
 
6
- (() => {
7
- 'use strict';
8
 
9
- class ConfigUI {
10
- constructor() {
11
- this.config = window.AIMHSA?.Config;
12
- this.init();
13
- }
14
-
15
- init() {
16
- this.createConfigPanel();
17
- this.bindEvents();
18
- console.log('⚙️ Configuration UI initialized');
19
- }
20
-
21
- /**
22
- * Create configuration panel
23
- */
24
- createConfigPanel() {
25
- const configPanel = document.createElement('div');
26
- configPanel.id = 'configPanel';
27
- configPanel.className = 'config-panel';
28
- configPanel.innerHTML = `
29
- <div class="config-header">
30
- <h3><i class="fas fa-cog"></i> Configuration</h3>
31
- <button class="btn btn-sm btn-outline-secondary" id="toggleConfigPanel">
32
- <i class="fas fa-times"></i>
33
- </button>
34
- </div>
35
- <div class="config-content">
36
- <div class="config-section">
37
- <h4>API Configuration</h4>
38
- <div class="form-group">
39
- <label>API Base URL</label>
40
- <input type="url" id="apiBaseUrl" class="form-control"
41
- value="${this.config?.getApiBaseUrl() || ''}"
42
- placeholder="https://prodevroger-ishingiro.hf.space">
43
- <small class="form-text text-muted">
44
- Base URL for the backend API server
45
- </small>
46
- </div>
47
- <div class="form-group">
48
- <label>Environment</label>
49
- <select id="environment" class="form-control">
50
- <option value="development">Development</option>
51
- <option value="staging">Staging</option>
52
- <option value="production">Production</option>
53
- </select>
54
  </div>
55
- <button class="btn btn-primary btn-sm" id="testConnection">
56
- <i class="fas fa-plug"></i> Test Connection
57
- </button>
58
- </div>
59
-
60
- <div class="config-section">
61
- <h4>UI Configuration</h4>
62
- <div class="form-group">
63
- <label>Theme</label>
64
- <select id="theme" class="form-control">
65
- <option value="dark">Dark</option>
66
- <option value="light">Light</option>
67
- </select>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
  </div>
69
- <div class="form-group">
70
- <label>Auto-refresh Interval (seconds)</label>
71
- <input type="number" id="autoRefresh" class="form-control"
72
- value="${this.config?.get('ui.autoRefreshInterval', 30000) / 1000}"
73
- min="5" max="300">
74
  </div>
75
  </div>
76
-
77
- <div class="config-actions">
78
- <button class="btn btn-success btn-sm" id="saveConfig">
79
- <i class="fas fa-save"></i> Save Configuration
80
- </button>
81
- <button class="btn btn-warning btn-sm" id="resetConfig">
82
- <i class="fas fa-undo"></i> Reset to Defaults
83
- </button>
84
- </div>
85
-
86
- <div class="config-info">
87
- <h4>Environment Information</h4>
88
- <pre id="envInfo"></pre>
89
- </div>
90
  </div>
91
- `;
92
-
93
- // Add styles
94
- const style = document.createElement('style');
95
- style.textContent = `
96
- .config-panel {
97
- position: fixed;
98
- top: 20px;
99
- right: -400px;
100
- width: 380px;
101
- height: calc(100vh - 40px);
102
- background: var(--surface, #1e293b);
103
- border: 1px solid var(--border, #334155);
104
- border-radius: 12px;
105
- box-shadow: 0 10px 25px rgba(0,0,0,0.3);
106
- z-index: 10000;
107
- transition: right 0.3s ease;
108
- overflow-y: auto;
109
- }
110
-
111
- .config-panel.open {
112
- right: 20px;
113
- }
114
-
115
- .config-header {
116
- display: flex;
117
- justify-content: space-between;
118
- align-items: center;
119
- padding: 1rem;
120
- border-bottom: 1px solid var(--border, #334155);
121
- background: var(--primary, #7c3aed);
122
- color: white;
123
- border-radius: 12px 12px 0 0;
124
- }
125
-
126
- .config-header h3 {
127
- margin: 0;
128
- font-size: 1.1rem;
129
- }
130
-
131
- .config-content {
132
- padding: 1rem;
133
- }
134
-
135
- .config-section {
136
- margin-bottom: 1.5rem;
137
- padding-bottom: 1rem;
138
- border-bottom: 1px solid var(--border-light, #475569);
139
- }
140
-
141
- .config-section:last-child {
142
- border-bottom: none;
143
- }
144
-
145
- .config-section h4 {
146
- color: var(--text, #f8fafc);
147
- font-size: 1rem;
148
- margin-bottom: 1rem;
149
- }
150
-
151
- .config-actions {
152
- display: flex;
153
- gap: 0.5rem;
154
- margin-bottom: 1rem;
155
- }
156
-
157
- .config-info pre {
158
- background: var(--background, #0f172a);
159
- padding: 0.5rem;
160
- border-radius: 4px;
161
- font-size: 0.8rem;
162
- color: var(--text-secondary, #cbd5e1);
163
- border: 1px solid var(--border, #334155);
164
- max-height: 200px;
165
- overflow-y: auto;
166
- }
167
-
168
- .config-toggle {
169
- position: fixed;
170
- top: 20px;
171
- right: 20px;
172
- z-index: 9999;
173
- background: var(--primary, #7c3aed);
174
- color: white;
175
- border: none;
176
- border-radius: 50%;
177
- width: 50px;
178
- height: 50px;
179
- display: flex;
180
- align-items: center;
181
- justify-content: center;
182
- font-size: 1.2rem;
183
- cursor: pointer;
184
- transition: all 0.3s ease;
185
- box-shadow: 0 4px 12px rgba(124, 58, 237, 0.3);
186
- }
187
-
188
- .config-toggle:hover {
189
- background: var(--primary-dark, #5b21b6);
190
- transform: scale(1.1);
191
- }
192
- `;
193
-
194
- document.head.appendChild(style);
195
- document.body.appendChild(configPanel);
196
-
197
- // Create toggle button
198
- const toggleBtn = document.createElement('button');
199
- toggleBtn.id = 'configToggle';
200
- toggleBtn.className = 'config-toggle';
201
- toggleBtn.innerHTML = '<i class="fas fa-cog"></i>';
202
- toggleBtn.title = 'Configuration Settings';
203
- document.body.appendChild(toggleBtn);
204
-
205
- this.updateEnvironmentInfo();
206
- }
207
-
208
- /**
209
- * Bind event handlers
210
- */
211
- bindEvents() {
212
- // Toggle panel
213
- document.getElementById('configToggle').addEventListener('click', () => {
214
- this.togglePanel();
215
- });
216
-
217
- document.getElementById('toggleConfigPanel').addEventListener('click', () => {
218
- this.togglePanel();
219
- });
220
-
221
- // Save configuration
222
- document.getElementById('saveConfig').addEventListener('click', () => {
223
- this.saveConfiguration();
224
- });
225
-
226
- // Reset configuration
227
- document.getElementById('resetConfig').addEventListener('click', () => {
228
- this.resetConfiguration();
229
- });
230
-
231
- // Test connection
232
- document.getElementById('testConnection').addEventListener('click', () => {
233
- this.testConnection();
234
- });
235
-
236
- // Real-time updates
237
- document.getElementById('apiBaseUrl').addEventListener('input', (e) => {
238
- if (this.config) {
239
- this.config.setApiBaseUrl(e.target.value);
240
- }
241
- });
242
-
243
- // Close panel on Escape key
244
- document.addEventListener('keydown', (e) => {
245
- if (e.key === 'Escape') {
246
- this.closePanel();
247
- }
248
- });
249
- }
250
-
251
- /**
252
- * Toggle configuration panel
253
- */
254
- togglePanel() {
255
- const panel = document.getElementById('configPanel');
256
- panel.classList.toggle('open');
257
-
258
- if (panel.classList.contains('open')) {
259
- this.loadCurrentSettings();
260
- this.updateEnvironmentInfo();
261
- }
262
- }
263
-
264
- /**
265
- * Close configuration panel
266
- */
267
- closePanel() {
268
- const panel = document.getElementById('configPanel');
269
- panel.classList.remove('open');
270
  }
271
-
272
- /**
273
- * Load current settings into UI
274
- */
275
- loadCurrentSettings() {
276
- if (!this.config) return;
277
-
278
- document.getElementById('apiBaseUrl').value = this.config.getApiBaseUrl();
279
- document.getElementById('environment').value = this.config.environment;
280
- document.getElementById('theme').value = this.config.get('ui.theme', 'dark');
281
- document.getElementById('autoRefresh').value = this.config.get('ui.autoRefreshInterval', 30000) / 1000;
282
  }
283
-
284
- /**
285
- * Save configuration
286
- */
287
- saveConfiguration() {
288
- if (!this.config) return;
289
-
290
- const apiBaseUrl = document.getElementById('apiBaseUrl').value;
291
- const environment = document.getElementById('environment').value;
292
- const theme = document.getElementById('theme').value;
293
- const autoRefresh = parseInt(document.getElementById('autoRefresh').value) * 1000;
294
-
295
- // Update configuration
296
- this.config.setApiBaseUrl(apiBaseUrl);
297
- this.config.set('ui.theme', theme);
298
- this.config.set('ui.autoRefreshInterval', autoRefresh);
299
-
300
- // Show success message
301
- this.showToast('Configuration saved successfully!', 'success');
302
-
303
- // Optionally reload the page to apply changes
304
- if (confirm('Configuration saved. Reload the page to apply changes?')) {
305
- window.location.reload();
306
- }
307
  }
308
-
309
- /**
310
- * Reset configuration to defaults
311
- */
312
- resetConfiguration() {
313
- if (!this.config) return;
314
-
315
- if (confirm('Are you sure you want to reset all configuration to defaults?')) {
316
- this.config.reset();
317
- this.loadCurrentSettings();
318
- this.updateEnvironmentInfo();
319
- this.showToast('Configuration reset to defaults', 'info');
320
- }
321
  }
322
-
323
- /**
324
- * Test API connection
325
- */
326
- async testConnection() {
327
- if (!this.config) return;
328
-
329
- const button = document.getElementById('testConnection');
330
- const originalText = button.innerHTML;
331
-
332
- button.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Testing...';
333
- button.disabled = true;
334
-
335
- try {
336
- const isConnected = await this.config.validateApiConnection();
337
-
338
- if (isConnected) {
339
- this.showToast('API connection successful!', 'success');
340
- } else {
341
- this.showToast('API connection failed', 'error');
342
- }
343
- } catch (error) {
344
- this.showToast('Connection test failed: ' + error.message, 'error');
345
- } finally {
346
- button.innerHTML = originalText;
347
- button.disabled = false;
348
- }
 
 
 
 
 
 
 
349
  }
350
-
351
- /**
352
- * Update environment information display
353
- */
354
- updateEnvironmentInfo() {
355
- if (!this.config) return;
356
-
357
- const envInfo = this.config.getEnvironmentInfo();
358
- const formattedInfo = JSON.stringify(envInfo, null, 2);
359
- document.getElementById('envInfo').textContent = formattedInfo;
 
 
360
  }
361
-
362
- /**
363
- * Show toast notification
364
- */
365
- showToast(message, type = 'info') {
366
- // Use SweetAlert2 if available
367
- if (typeof Swal !== 'undefined') {
368
- Swal.fire({
369
- toast: true,
370
- position: 'top-end',
371
- showConfirmButton: false,
372
- timer: 3000,
373
- icon: type === 'error' ? 'error' : type === 'success' ? 'success' : 'info',
374
- title: message
375
- });
376
- return;
 
 
 
 
 
 
 
 
 
 
377
  }
378
-
379
- // Fallback to simple alert
380
- const alertClass = type === 'error' ? 'alert-danger' :
381
- type === 'success' ? 'alert-success' : 'alert-info';
382
-
383
- const toast = document.createElement('div');
384
- toast.className = `alert ${alertClass} alert-dismissible fade show`;
385
- toast.style.cssText = `
386
- position: fixed;
387
- top: 20px;
388
- left: 50%;
389
- transform: translateX(-50%);
390
- z-index: 10001;
391
- min-width: 300px;
392
- `;
393
- toast.innerHTML = `
394
- ${message}
395
- <button type="button" class="close" onclick="this.parentElement.remove()">
396
- <span>&times;</span>
397
- </button>
398
- `;
399
-
400
- document.body.appendChild(toast);
401
-
402
- setTimeout(() => {
403
- if (toast.parentElement) {
404
- toast.remove();
405
- }
406
- }, 3000);
407
  }
408
  }
 
409
 
410
- // Initialize when DOM is ready
411
- if (document.readyState === 'loading') {
412
- document.addEventListener('DOMContentLoaded', () => {
413
- new ConfigUI();
414
- });
415
- } else {
416
- new ConfigUI();
417
- }
418
 
419
- })();
 
 
 
 
1
  /**
2
+ * AIMHSA Configuration UI Management
3
  * Provides UI components for managing frontend configuration
4
  */
5
 
6
+ window.AIMHSA = window.AIMHSA || {};
 
7
 
8
+ // Configuration UI class for managing settings interface
9
+ class AIMHSAConfigUI {
10
+ constructor() {
11
+ this.isInitialized = false;
12
+ this.settingsModal = null;
13
+ }
14
+
15
+ init() {
16
+ if (this.isInitialized) return;
17
+
18
+ this.createSettingsModal();
19
+ this.bindEvents();
20
+ this.isInitialized = true;
21
+ }
22
+
23
+ createSettingsModal() {
24
+ // Create settings modal HTML
25
+ const modalHTML = `
26
+ <div id="aimhsa-settings-modal" class="modal fade" tabindex="-1" role="dialog">
27
+ <div class="modal-dialog" role="document">
28
+ <div class="modal-content">
29
+ <div class="modal-header">
30
+ <h5 class="modal-title">AIMHSA Settings</h5>
31
+ <button type="button" class="close" data-dismiss="modal">
32
+ <span>&times;</span>
33
+ </button>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  </div>
35
+ <div class="modal-body">
36
+ <form id="aimhsa-settings-form">
37
+ <div class="form-group">
38
+ <label for="api-base-url">API Base URL</label>
39
+ <input type="url" class="form-control" id="api-base-url"
40
+ placeholder="https://your-domain.com">
41
+ <small class="form-text text-muted">
42
+ Base URL for API requests. Leave empty for auto-detection.
43
+ </small>
44
+ </div>
45
+
46
+ <div class="form-group">
47
+ <label for="environment">Environment</label>
48
+ <select class="form-control" id="environment">
49
+ <option value="production">Production</option>
50
+ <option value="development">Development</option>
51
+ <option value="staging">Staging</option>
52
+ </select>
53
+ </div>
54
+
55
+ <div class="form-group">
56
+ <div class="custom-control custom-checkbox">
57
+ <input type="checkbox" class="custom-control-input" id="debug-mode">
58
+ <label class="custom-control-label" for="debug-mode">
59
+ Enable Debug Mode
60
+ </label>
61
+ </div>
62
+ </div>
63
+ </form>
64
  </div>
65
+ <div class="modal-footer">
66
+ <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
67
+ <button type="button" class="btn btn-danger" id="reset-config">Reset to Defaults</button>
68
+ <button type="button" class="btn btn-primary" id="save-config">Save Changes</button>
 
69
  </div>
70
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
  </div>
72
+ </div>
73
+ `;
74
+
75
+ // Append to body if not exists
76
+ if (!document.getElementById('aimhsa-settings-modal')) {
77
+ document.body.insertAdjacentHTML('beforeend', modalHTML);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  }
79
+
80
+ this.settingsModal = document.getElementById('aimhsa-settings-modal');
81
+ }
82
+
83
+ bindEvents() {
84
+ // Save configuration
85
+ const saveBtn = document.getElementById('save-config');
86
+ if (saveBtn) {
87
+ saveBtn.addEventListener('click', () => this.saveConfiguration());
 
 
88
  }
89
+
90
+ // Reset configuration
91
+ const resetBtn = document.getElementById('reset-config');
92
+ if (resetBtn) {
93
+ resetBtn.addEventListener('click', () => this.resetConfiguration());
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  }
95
+
96
+ // Load configuration when modal opens
97
+ if (this.settingsModal) {
98
+ this.settingsModal.addEventListener('show.bs.modal', () => this.loadConfiguration());
 
 
 
 
 
 
 
 
 
99
  }
100
+ }
101
+
102
+ loadConfiguration() {
103
+ const config = window.AIMHSA.Config;
104
+
105
+ // Populate form fields
106
+ const apiUrlField = document.getElementById('api-base-url');
107
+ const environmentField = document.getElementById('environment');
108
+ const debugModeField = document.getElementById('debug-mode');
109
+
110
+ if (apiUrlField) apiUrlField.value = config.get('apiBaseUrl') || '';
111
+ if (environmentField) environmentField.value = config.get('environment') || 'production';
112
+ if (debugModeField) debugModeField.checked = config.get('debugMode') || false;
113
+ }
114
+
115
+ saveConfiguration() {
116
+ const config = window.AIMHSA.Config;
117
+
118
+ // Get form values
119
+ const apiUrl = document.getElementById('api-base-url')?.value?.trim();
120
+ const environment = document.getElementById('environment')?.value;
121
+ const debugMode = document.getElementById('debug-mode')?.checked;
122
+
123
+ // Update configuration
124
+ if (apiUrl) config.set('apiBaseUrl', apiUrl);
125
+ config.set('environment', environment);
126
+ config.set('debugMode', debugMode);
127
+
128
+ // Show success message
129
+ this.showNotification('Configuration saved successfully!', 'success');
130
+
131
+ // Close modal
132
+ if (window.jQuery && window.jQuery.fn.modal) {
133
+ window.jQuery(this.settingsModal).modal('hide');
134
  }
135
+
136
+ // Refresh page to apply changes
137
+ setTimeout(() => {
138
+ window.location.reload();
139
+ }, 1000);
140
+ }
141
+
142
+ resetConfiguration() {
143
+ if (confirm('Are you sure you want to reset all settings to defaults?')) {
144
+ window.AIMHSA.Config.reset();
145
+ this.loadConfiguration();
146
+ this.showNotification('Configuration reset to defaults!', 'info');
147
  }
148
+ }
149
+
150
+ showNotification(message, type = 'info') {
151
+ // Create notification element
152
+ const notification = document.createElement('div');
153
+ notification.className = `alert alert-${type} alert-dismissible fade show`;
154
+ notification.style.cssText = `
155
+ position: fixed;
156
+ top: 20px;
157
+ right: 20px;
158
+ z-index: 9999;
159
+ min-width: 300px;
160
+ `;
161
+ notification.innerHTML = `
162
+ ${message}
163
+ <button type="button" class="close" data-dismiss="alert">
164
+ <span>&times;</span>
165
+ </button>
166
+ `;
167
+
168
+ document.body.appendChild(notification);
169
+
170
+ // Auto-remove after 3 seconds
171
+ setTimeout(() => {
172
+ if (notification.parentNode) {
173
+ notification.parentNode.removeChild(notification);
174
  }
175
+ }, 3000);
176
+ }
177
+
178
+ openSettings() {
179
+ if (!this.isInitialized) this.init();
180
+
181
+ if (window.jQuery && window.jQuery.fn.modal) {
182
+ window.jQuery(this.settingsModal).modal('show');
183
+ } else {
184
+ // Fallback for non-Bootstrap environments
185
+ this.settingsModal.style.display = 'block';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
186
  }
187
  }
188
+ }
189
 
190
+ // Initialize global configuration UI
191
+ window.AIMHSA.ConfigUI = new AIMHSAConfigUI();
192
+
193
+ // Auto-initialize when DOM is ready
194
+ document.addEventListener('DOMContentLoaded', () => {
195
+ window.AIMHSA.ConfigUI.init();
196
+ });
 
197
 
198
+ // Export for module systems if available
199
+ if (typeof module !== 'undefined' && module.exports) {
200
+ module.exports = AIMHSAConfigUI;
201
+ }