chenguittiMaroua commited on
Commit
9a97ee3
·
verified ·
1 Parent(s): 5098252

Update static/indexAI.html

Browse files
Files changed (1) hide show
  1. static/indexAI.html +110 -484
static/indexAI.html CHANGED
@@ -1,380 +1,105 @@
1
-
2
- <!--
3
- <!DOCTYPE html>
4
- <html lang="en">
5
- <head>
6
- <meta charset="UTF-8" />
7
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
8
- <title>Modern AI Website</title>
9
- <link rel="stylesheet" href="static/test.css" />
10
- <script defer src="static/test.js"></script>
11
- </head>
12
- <body>
13
- <header>
14
- <h1>AI Toolbox</h1>
15
- <p>Explore powerful AI tools below</p>
16
- </header>
17
-
18
- <main>
19
- <section class="cards">
20
- <div class="card" onclick="showSection('summarizer')">
21
- <div class="icon">📝</div>
22
- <h2>Text Summarizer</h2>
23
- <p>Summarize long articles into concise content.</p>
24
- </div>
25
- <div class="card" onclick="showSection('image-caption')">
26
- <div class="icon">🖼️</div>
27
- <h2>Image Captioning</h2>
28
- <p>Upload an image to get a smart caption.</p>
29
- </div>
30
- <div class="card" onclick="showSection('code-explainer')">
31
- <div class="icon">💡</div>
32
- <h2>Code Explainer</h2>
33
- <p>Understand what your code really does.</p>
34
- </div>
35
- </section>
36
-
37
- <section id="summarizer" class="tool-section">
38
- <h3>Text Summarizer</h3>
39
- <textarea placeholder="Paste your article here..."></textarea>
40
- <button>Summarize</button>
41
- </section>
42
-
43
- <section id="image-caption" class="tool-section">
44
- <h3>Image Captioning</h3>
45
- <input type="file" accept="image/*">
46
- <button>Generate Caption</button>
47
- </section>
48
-
49
- <section id="code-explainer" class="tool-section">
50
- <h3>Code Explainer</h3>
51
- <textarea placeholder="Paste your code snippet here..."></textarea>
52
- <button>Explain Code</button>
53
- </section>
54
- </main>
55
-
56
- <footer>
57
- <p>© 2025 AI Toolbox. All rights reserved.</p>
58
- </footer>
59
- </body>
60
- </html>-->
61
  <!DOCTYPE html>
62
- <html lang="en">
63
  <head>
64
- <meta charset="UTF-8">
65
- <meta name="viewport" content="width=device-width, initial-scale=1.0">
66
- <title>Excel Data Visualizer</title>
67
  <style>
68
- :root {
69
- --primary-color: #4CAF50;
70
- --secondary-color: #f8f9fa;
71
- --text-color: #333;
72
- --border-color: #ddd;
73
- --error-color: #dc3545;
74
- }
75
-
76
- body {
77
- font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
78
- line-height: 1.6;
79
- color: var(--text-color);
80
- max-width: 900px;
81
- margin: 0 auto;
82
- padding: 20px;
83
- background-color: #f5f5f5;
84
- }
85
-
86
- .container {
87
- background-color: white;
88
- border-radius: 8px;
89
- box-shadow: 0 2px 10px rgba(0,0,0,0.1);
90
- padding: 30px;
91
- }
92
-
93
- h1 {
94
- color: var(--primary-color);
95
- text-align: center;
96
- margin-bottom: 30px;
97
- }
98
-
99
- .upload-area {
100
- border: 2px dashed var(--border-color);
101
- border-radius: 6px;
102
- padding: 30px;
103
- text-align: center;
104
- cursor: pointer;
105
- transition: all 0.3s;
106
- margin-bottom: 20px;
107
- background-color: var(--secondary-color);
108
- }
109
-
110
- .upload-area:hover {
111
- border-color: var(--primary-color);
112
- background-color: rgba(76, 175, 80, 0.05);
113
- }
114
-
115
- .upload-area.highlight {
116
- border-color: var(--primary-color);
117
- background-color: rgba(76, 175, 80, 0.1);
118
- }
119
-
120
- #file-input {
121
- display: none;
122
- }
123
-
124
- .form-group {
125
- margin-bottom: 20px;
126
- }
127
-
128
- label {
129
- display: block;
130
- margin-bottom: 8px;
131
- font-weight: 600;
132
- }
133
-
134
- input[type="text"],
135
- textarea,
136
- select {
137
- width: 100%;
138
- padding: 12px;
139
- border: 1px solid var(--border-color);
140
- border-radius: 4px;
141
- font-size: 16px;
142
- transition: border 0.3s;
143
- }
144
-
145
- textarea {
146
- min-height: 100px;
147
- resize: vertical;
148
- }
149
-
150
- input[type="text"]:focus,
151
- textarea:focus,
152
- select:focus {
153
- outline: none;
154
- border-color: var(--primary-color);
155
- box-shadow: 0 0 0 3px rgba(76, 175, 80, 0.2);
156
- }
157
-
158
- button {
159
- background-color: var(--primary-color);
160
- color: white;
161
- border: none;
162
- padding: 12px 20px;
163
- font-size: 16px;
164
- border-radius: 4px;
165
- cursor: pointer;
166
- width: 100%;
167
- transition: background-color 0.3s;
168
- font-weight: 600;
169
- text-transform: uppercase;
170
- letter-spacing: 1px;
171
- }
172
-
173
- button:hover {
174
- background-color: #45a049;
175
- }
176
-
177
- button:disabled {
178
- background-color: #cccccc;
179
- cursor: not-allowed;
180
- }
181
-
182
- #result-container {
183
- margin-top: 30px;
184
- display: none;
185
- }
186
-
187
- #result-image {
188
- max-width: 100%;
189
- border-radius: 6px;
190
- box-shadow: 0 2px 8px rgba(0,0,0,0.1);
191
- margin-bottom: 20px;
192
- }
193
-
194
- .code-block {
195
- background-color: #f8f8f8;
196
- padding: 15px;
197
- border-radius: 4px;
198
- overflow-x: auto;
199
- font-family: 'Courier New', Courier, monospace;
200
- border: 1px solid var(--border-color);
201
- }
202
-
203
- #error-message {
204
- color: var(--error-color);
205
- background-color: #f8d7da;
206
- padding: 15px;
207
- border-radius: 4px;
208
- margin-top: 20px;
209
- border: 1px solid #f5c6cb;
210
- white-space: pre-line;
211
- display: none;
212
- }
213
-
214
- .loading {
215
- display: inline-block;
216
- width: 20px;
217
- height: 20px;
218
- border: 3px solid rgba(255,255,255,.3);
219
- border-radius: 50%;
220
- border-top-color: white;
221
- animation: spin 1s ease-in-out infinite;
222
- margin-right: 10px;
223
- }
224
-
225
- @keyframes spin {
226
- to { transform: rotate(360deg); }
227
- }
228
-
229
- .columns-info {
230
- background-color: #e9f7ef;
231
- padding: 15px;
232
- border-radius: 4px;
233
- margin-bottom: 20px;
234
- border: 1px solid #c8e6d1;
235
- }
236
-
237
- .columns-info h3 {
238
- margin-top: 0;
239
- color: #2e7d32;
240
- }
241
-
242
- .columns-list {
243
- display: flex;
244
- flex-wrap: wrap;
245
- gap: 8px;
246
- }
247
-
248
- .column-tag {
249
- background-color: #c8e6d1;
250
- padding: 4px 8px;
251
- border-radius: 4px;
252
- font-size: 14px;
253
- }
254
  </style>
255
  </head>
256
  <body>
257
- <div class="container">
258
- <h1>Excel Data Visualizer</h1>
259
-
260
- <div class="upload-area" id="drop-area">
261
- <p id="file-instructions">Drag & drop your Excel file here or click to browse</p>
262
- <input type="file" id="file-input" accept=".xlsx,.xls">
263
- </div>
264
-
265
- <div class="form-group">
266
- <label for="prompt">Visualization Prompt</label>
267
- <textarea id="prompt" rows="3" placeholder="Example: Show sales trends by month"></textarea>
268
- <p class="hint">Describe the visualization you want (e.g., "Compare revenue by region")</p>
269
- </div>
270
-
271
- <div class="form-group">
272
- <label for="style">Chart Style</label>
273
- <select id="style">
274
- <option value="seaborn-v0_8">Seaborn (Default)</option>
275
- <option value="ggplot">ggplot</option>
276
- <option value="dark_background">Dark Background</option>
277
- <option value="bmh">Bayesian Methods for Hackers</option>
278
- <option value="fivethirtyeight">FiveThirtyEight</option>
279
- </select>
 
 
 
 
 
 
 
 
 
 
280
  </div>
281
 
282
- <button id="visualize-btn">
283
- <span id="btn-text">Generate Visualization</span>
284
- </button>
285
-
286
- <div id="error-message"></div>
287
 
288
- <div id="columns-info" class="columns-info" style="display: none;">
289
- <h3>Detected Columns</h3>
290
- <div class="columns-list" id="columns-list"></div>
291
- <p>Tip: Reference these column names in your prompt for better results</p>
292
- </div>
293
-
294
- <div id="result-container">
295
- <h2>Your Visualization</h2>
296
- <img id="result-image">
297
-
298
- <div class="form-group">
299
- <label for="chart-title">Chart Title</label>
300
- <input type="text" id="chart-title" placeholder="Custom chart title">
301
- </div>
302
-
303
- <button id="update-btn">Update Visualization</button>
304
-
305
- <h3>Generated Python Code</h3>
306
- <pre class="code-block" id="generated-code"></pre>
307
-
308
- <div class="form-group">
309
- <label for="code-feedback">Feedback on this visualization</label>
310
- <textarea id="code-feedback" rows="2" placeholder="Was this what you expected? Any improvements?"></textarea>
311
- <button id="feedback-btn">Send Feedback</button>
312
- </div>
313
- </div>
314
  </div>
315
 
316
  <script>
317
  // DOM Elements
318
  const dropArea = document.getElementById('drop-area');
319
  const fileInput = document.getElementById('file-input');
320
- const fileInstructions = document.getElementById('file-instructions');
321
  const visualizeBtn = document.getElementById('visualize-btn');
322
- const btnText = document.getElementById('btn-text');
323
  const resultContainer = document.getElementById('result-container');
324
  const resultImage = document.getElementById('result-image');
325
  const generatedCode = document.getElementById('generated-code');
326
  const errorMessage = document.getElementById('error-message');
327
- const columnsInfo = document.getElementById('columns-info');
328
- const columnsList = document.getElementById('columns-list');
329
- const chartTitle = document.getElementById('chart-title');
330
  const updateBtn = document.getElementById('update-btn');
331
- const feedbackBtn = document.getElementById('feedback-btn');
332
 
333
- // State
334
- let currentData = null;
335
-
336
- // Initialize
337
- document.addEventListener('DOMContentLoaded', () => {
338
- setupEventListeners();
339
  });
340
 
341
- function setupEventListeners() {
342
- // Drag and drop events
343
- ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
344
- dropArea.addEventListener(eventName, preventDefaults, false);
345
- });
346
-
347
- ['dragenter', 'dragover'].forEach(eventName => {
348
- dropArea.addEventListener(eventName, highlight, false);
349
- });
350
-
351
- ['dragleave', 'drop'].forEach(eventName => {
352
- dropArea.addEventListener(eventName, unhighlight, false);
353
- });
354
-
355
- dropArea.addEventListener('drop', handleDrop, false);
356
- dropArea.addEventListener('click', () => fileInput.click());
357
- fileInput.addEventListener('change', handleFileSelect);
358
-
359
- // Button events
360
- visualizeBtn.addEventListener('click', generateVisualization);
361
- updateBtn.addEventListener('click', updateVisualization);
362
- feedbackBtn.addEventListener('click', sendFeedback);
363
- }
364
-
365
  function preventDefaults(e) {
366
  e.preventDefault();
367
  e.stopPropagation();
368
  }
369
 
 
 
 
 
 
 
 
 
370
  function highlight() {
371
- dropArea.classList.add('highlight');
 
372
  }
373
 
374
  function unhighlight() {
375
- dropArea.classList.remove('highlight');
 
376
  }
377
 
 
 
 
 
378
  function handleDrop(e) {
379
  const dt = e.dataTransfer;
380
  const files = dt.files;
@@ -390,33 +115,12 @@
390
 
391
  function handleFiles(files) {
392
  const file = files[0];
 
393
  fileInput.files = files;
394
- fileInstructions.textContent = file.name;
395
-
396
- // Preview the file (just show name for Excel files)
397
- showFilePreview(file);
398
- }
399
-
400
- function showFilePreview(file) {
401
- // For Excel files, we'll just show the name
402
- const fileName = file.name;
403
- fileInstructions.innerHTML = `
404
- <strong>${fileName}</strong>
405
- <div>${(file.size / 1024 / 1024).toFixed(2)} MB</div>
406
- `;
407
-
408
- // Read the file to get columns (simplified example)
409
- previewExcelColumns(file);
410
- }
411
-
412
- function previewExcelColumns(file) {
413
- // In a real app, you might use SheetJS or similar to peek at the file
414
- // For this example, we'll just show a loading state
415
- columnsInfo.style.display = 'block';
416
- columnsList.innerHTML = '<div>Columns will appear after analysis</div>';
417
  }
418
 
419
- async function generateVisualization() {
 
420
  const file = fileInput.files[0];
421
  const prompt = document.getElementById('prompt').value;
422
  const style = document.getElementById('style').value;
@@ -427,9 +131,8 @@
427
  }
428
 
429
  try {
430
- // Show loading state
431
  visualizeBtn.disabled = true;
432
- btnText.innerHTML = '<span class="loading"></span> Processing...';
433
  hideError();
434
 
435
  const formData = new FormData();
@@ -442,140 +145,63 @@
442
  body: formData
443
  });
444
 
445
- const data = await response.json();
446
-
447
  if (!response.ok) {
448
- handleErrorResponse(data);
449
- return;
450
  }
451
 
452
- // Show results
453
- currentData = data;
454
- resultImage.src = `data:image/png;base64,${data.image_data}`;
455
- generatedCode.textContent = data.code;
456
- resultContainer.style.display = 'block';
457
-
458
- // Update columns info
459
- if (data.columns) {
460
- columnsList.innerHTML = '';
461
- data.columns.forEach(col => {
462
- const colElement = document.createElement('div');
463
- colElement.className = 'column-tag';
464
- colElement.textContent = col;
465
- columnsList.appendChild(colElement);
466
- });
467
- }
468
 
469
- // Set initial chart title
470
- if (data.prompt) {
471
- chartTitle.value = `Visualization: ${data.prompt.substring(0, 50)}`;
472
- document.getElementById('prompt').value = data.prompt;
 
 
 
473
  }
474
 
475
- // Scroll to results
476
- resultContainer.scrollIntoView({ behavior: 'smooth' });
477
-
478
  } catch (error) {
479
- showError("Network error: " + error.message);
480
  } finally {
481
  visualizeBtn.disabled = false;
482
- btnText.textContent = 'Generate Visualization';
483
  }
484
- }
485
-
486
- async function updateVisualization() {
487
- if (!currentData) return;
488
-
489
- try {
490
- updateBtn.disabled = true;
491
- updateBtn.innerHTML = '<span class="loading"></span> Updating...';
492
-
493
- const response = await fetch('/visualize/natural', {
494
- method: 'POST',
495
- body: createUpdateFormData()
496
- });
497
-
498
- const data = await response.json();
499
-
500
- if (!response.ok) {
501
- handleErrorResponse(data);
502
- return;
503
- }
504
-
505
- // Update results
506
- currentData = data;
507
- resultImage.src = `data:image/png;base64,${data.image_data}`;
508
- generatedCode.textContent = data.code;
509
-
510
- } catch (error) {
511
- showError("Update error: " + error.message);
512
- } finally {
513
- updateBtn.disabled = false;
514
- updateBtn.textContent = 'Update Visualization';
515
- }
516
- }
517
-
518
- function createUpdateFormData() {
519
- const formData = new FormData();
520
- formData.append('file', fileInput.files[0]);
521
- formData.append('prompt', document.getElementById('prompt').value);
522
- formData.append('style', document.getElementById('style').value);
523
- return formData;
524
- }
525
 
526
- async function sendFeedback() {
527
- const feedback = document.getElementById('code-feedback').value;
528
- if (!feedback.trim()) {
529
- showError("Please enter your feedback before sending");
 
530
  return;
531
  }
532
 
533
- try {
534
- feedbackBtn.disabled = true;
535
- feedbackBtn.innerHTML = '<span class="loading"></span> Sending...';
536
-
537
- // In a real app, you would send this to your backend
538
- // For now, we'll just show a confirmation
539
- setTimeout(() => {
540
- alert("Thank you for your feedback!");
541
- document.getElementById('code-feedback').value = '';
542
- feedbackBtn.disabled = false;
543
- feedbackBtn.textContent = 'Send Feedback';
544
- }, 1000);
545
-
546
- } catch (error) {
547
- showError("Failed to send feedback: " + error.message);
548
- feedbackBtn.disabled = false;
549
- feedbackBtn.textContent = 'Send Feedback';
550
- }
551
- }
552
-
553
- function handleErrorResponse(errorData) {
554
- let errorMsg = errorData.detail?.error || "Request failed";
555
-
556
- if (errorData.detail?.message) {
557
- errorMsg += `: ${errorData.detail.message}`;
558
- }
559
-
560
- if (errorData.detail?.suggestions) {
561
- errorMsg += "\n\nSuggestions:\n" +
562
- errorData.detail.suggestions.join("\n• ");
563
- }
564
-
565
- if (errorData.detail?.your_prompt) {
566
- errorMsg += `\n\nYour prompt was: "${errorData.detail.your_prompt}"`;
567
- }
568
-
569
- showError(errorMsg);
570
- }
571
 
572
  function showError(message) {
573
  errorMessage.textContent = message;
574
  errorMessage.style.display = 'block';
575
- resultContainer.style.display = 'none';
576
-
577
- // Scroll to error
578
- errorMessage.scrollIntoView({ behavior: 'smooth' });
579
  }
580
 
581
  function hideError() {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  <!DOCTYPE html>
2
+ <html>
3
  <head>
4
+ <title>Excel Visualizer</title>
 
 
5
  <style>
6
+ body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
7
+ .upload-area { border: 2px dashed #ccc; padding: 30px; text-align: center; cursor: pointer; margin-bottom: 20px; }
8
+ #preview { margin-top: 10px; font-weight: bold; }
9
+ #result-container { margin-top: 30px; display: none; }
10
+ #result-image { max-width: 100%; margin-bottom: 20px; }
11
+ .code-block { background: #f5f5f5; padding: 15px; overflow-x: auto; }
12
+ #error-message { color: red; margin-top: 20px; display: none; }
13
+ button { padding: 10px 15px; background: #4CAF50; color: white; border: none; cursor: pointer; }
14
+ button:disabled { background: #cccccc; }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
  </style>
16
  </head>
17
  <body>
18
+ <h1>Excel Data Visualizer</h1>
19
+
20
+ <div class="upload-area" id="drop-area">
21
+ <p>Drag & drop Excel file here or click to select</p>
22
+ <input type="file" id="file-input" accept=".xlsx,.xls" style="display: none;">
23
+ <div id="preview"></div>
24
+ </div>
25
+
26
+ <div>
27
+ <label for="prompt">Visualization Prompt:</label>
28
+ <textarea id="prompt" rows="3" style="width: 100%" placeholder="e.g. Show sales by region"></textarea>
29
+ </div>
30
+
31
+ <div>
32
+ <label for="style">Chart Style:</label>
33
+ <select id="style" style="width: 100%">
34
+ <option value="seaborn-v0_8">Seaborn</option>
35
+ <option value="ggplot">ggplot</option>
36
+ <option value="dark_background">Dark</option>
37
+ </select>
38
+ </div>
39
+
40
+ <button id="visualize-btn">Generate Visualization</button>
41
+
42
+ <div id="error-message"></div>
43
+
44
+ <div id="result-container">
45
+ <h2>Your Visualization</h2>
46
+ <img id="result-image">
47
+
48
+ <div>
49
+ <label for="chart-title">Chart Title:</label>
50
+ <input type="text" id="chart-title" style="width: 100%">
51
  </div>
52
 
53
+ <button id="update-btn">Update Visualization</button>
 
 
 
 
54
 
55
+ <h3>Generated Python Code</h3>
56
+ <pre class="code-block" id="generated-code"></pre>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
  </div>
58
 
59
  <script>
60
  // DOM Elements
61
  const dropArea = document.getElementById('drop-area');
62
  const fileInput = document.getElementById('file-input');
63
+ const preview = document.getElementById('preview');
64
  const visualizeBtn = document.getElementById('visualize-btn');
 
65
  const resultContainer = document.getElementById('result-container');
66
  const resultImage = document.getElementById('result-image');
67
  const generatedCode = document.getElementById('generated-code');
68
  const errorMessage = document.getElementById('error-message');
 
 
 
69
  const updateBtn = document.getElementById('update-btn');
 
70
 
71
+ // Drag and drop functionality
72
+ ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
73
+ dropArea.addEventListener(eventName, preventDefaults, false);
 
 
 
74
  });
75
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
  function preventDefaults(e) {
77
  e.preventDefault();
78
  e.stopPropagation();
79
  }
80
 
81
+ ['dragenter', 'dragover'].forEach(eventName => {
82
+ dropArea.addEventListener(eventName, highlight, false);
83
+ });
84
+
85
+ ['dragleave', 'drop'].forEach(eventName => {
86
+ dropArea.addEventListener(eventName, unhighlight, false);
87
+ });
88
+
89
  function highlight() {
90
+ dropArea.style.borderColor = '#4CAF50';
91
+ dropArea.style.backgroundColor = 'rgba(76, 175, 80, 0.1)';
92
  }
93
 
94
  function unhighlight() {
95
+ dropArea.style.borderColor = '#ccc';
96
+ dropArea.style.backgroundColor = '';
97
  }
98
 
99
+ dropArea.addEventListener('drop', handleDrop, false);
100
+ dropArea.addEventListener('click', () => fileInput.click());
101
+ fileInput.addEventListener('change', handleFileSelect);
102
+
103
  function handleDrop(e) {
104
  const dt = e.dataTransfer;
105
  const files = dt.files;
 
115
 
116
  function handleFiles(files) {
117
  const file = files[0];
118
+ preview.innerHTML = `Selected: <strong>${file.name}</strong> (${(file.size/1024/1024).toFixed(2)} MB)`;
119
  fileInput.files = files;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  }
121
 
122
+ // Visualization functionality
123
+ visualizeBtn.addEventListener('click', async () => {
124
  const file = fileInput.files[0];
125
  const prompt = document.getElementById('prompt').value;
126
  const style = document.getElementById('style').value;
 
131
  }
132
 
133
  try {
 
134
  visualizeBtn.disabled = true;
135
+ visualizeBtn.textContent = "Processing...";
136
  hideError();
137
 
138
  const formData = new FormData();
 
145
  body: formData
146
  });
147
 
 
 
148
  if (!response.ok) {
149
+ const error = await response.json();
150
+ throw new Error(error.detail || "Failed to generate visualization");
151
  }
152
 
153
+ const result = await response.json();
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
154
 
155
+ if (result.status === "success") {
156
+ resultImage.src = `data:image/png;base64,${result.image}`;
157
+ generatedCode.textContent = result.code;
158
+ document.getElementById('chart-title').value = result.title || "My Chart";
159
+ resultContainer.style.display = 'block';
160
+ } else {
161
+ throw new Error(result.message || "Visualization failed");
162
  }
163
 
 
 
 
164
  } catch (error) {
165
+ showError(error.message);
166
  } finally {
167
  visualizeBtn.disabled = false;
168
+ visualizeBtn.textContent = "Generate Visualization";
169
  }
170
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
 
172
+ // Update functionality
173
+ updateBtn.addEventListener('click', async () => {
174
+ const title = document.getElementById('chart-title').value;
175
+ if (!title) {
176
+ showError("Please enter a chart title");
177
  return;
178
  }
179
 
180
+ // Here you would typically send the update request to your backend
181
+ // For now we'll just update the title in the image (mock implementation)
182
+ const canvas = document.createElement('canvas');
183
+ const ctx = canvas.getContext('2d');
184
+ const img = new Image();
185
+
186
+ img.onload = function() {
187
+ canvas.width = img.width;
188
+ canvas.height = img.height + 40;
189
+ ctx.fillStyle = 'white';
190
+ ctx.fillRect(0, 0, canvas.width, canvas.height);
191
+ ctx.drawImage(img, 0, 40);
192
+ ctx.fillStyle = 'black';
193
+ ctx.font = '20px Arial';
194
+ ctx.textAlign = 'center';
195
+ ctx.fillText(title, canvas.width/2, 30);
196
+ resultImage.src = canvas.toDataURL();
197
+ };
198
+
199
+ img.src = resultImage.src;
200
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
201
 
202
  function showError(message) {
203
  errorMessage.textContent = message;
204
  errorMessage.style.display = 'block';
 
 
 
 
205
  }
206
 
207
  function hideError() {