Hadiil commited on
Commit
0bc45e2
·
verified ·
1 Parent(s): 5f084b1

Update static/scripts.js

Browse files
Files changed (1) hide show
  1. static/scripts.js +353 -239
static/scripts.js CHANGED
@@ -1,239 +1,353 @@
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>Cosmic AI Assistant</title>
7
- <link rel="stylesheet" href="/static/styles.css">
8
- <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
9
- </head>
10
- <body class="bg-black text-white font-sans">
11
- <!-- Starry Background -->
12
- <div class="stars"></div>
13
-
14
- <!-- Chatbot Icon -->
15
- <div class="chatbot-icon" title="Chat with Gemini">
16
- <img src="/images/gemini-icon.png" alt="Gemini Chatbot" class="w-12 h-12">
17
- </div>
18
-
19
- <!-- Main Container -->
20
- <div class="container mx-auto p-6">
21
- <h1 class="text-4xl font-bold text-center mb-8 cosmic-gradient">Cosmic AI Assistant</h1>
22
- <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
23
- <!-- Summarize Box -->
24
- <div class="function-box card" data-modal="summarize-modal">
25
- <img src="/images/summarize.png" alt="Summarize Icon" class="w-20 h-20 mx-auto mb-4">
26
- <h2 class="text-2xl font-semibold text-center">Summarize Text</h2>
27
- <p class="text-base text-center text-gray-300">Shorten long text or files into concise summaries.</p>
28
- </div>
29
- <!-- Translate Box -->
30
- <div class="function-box card" data-modal="translate-modal">
31
- <img src="/images/translate.png" alt="Translate Icon" class="w-20 h-20 mx-auto mb-4">
32
- <h2 class="text-2xl font-semibold text-center">Translate</h2>
33
- <p class="text-base text-center text-gray-300">Convert text or files to another language.</p>
34
- </div>
35
- <!-- File QA Box -->
36
- <div class="function-box card" data-modal="file-qa-modal">
37
- <img src="/images/file-qa.png" alt="File QA Icon" class="w-20 h-20 mx-auto mb-4">
38
- <h2 class="text-2xl font-semibold text-center">Ask About File</h2>
39
- <p class="text-base text-center text-gray-300">Ask questions about uploaded documents.</p>
40
- </div>
41
- <!-- Image Captioning Box -->
42
- <div class="function-box card" data-modal="image-caption-modal">
43
- <img src="/images/image-caption.png" alt="Image Caption Icon" class="w-20 h-20 mx-auto mb-4">
44
- <h2 class="text-2xl font-semibold text-center">Image Caption</h2>
45
- <p class="text-base text-center text-gray-300">Get descriptions for your images.</p>
46
- </div>
47
- <!-- Visual QA Box -->
48
- <div class="function-box card" data-modal="visual-qa-modal">
49
- <img src="/images/visual-qa.png" alt="Visual QA Icon" class="w-20 h-20 mx-auto mb-4">
50
- <h2 class="text-2xl font-semibold text-center">Image Questions</h2>
51
- <p class="text-base text-center text-gray-300">Ask questions about images.</p>
52
- </div>
53
- <!-- Data Visualization Box -->
54
- <div class="function-box card" data-modal="visualize-modal">
55
- <img src="/images/visualize.png" alt="Visualize Icon" class="w-20 h-20 mx-auto mb-4">
56
- <h2 class="text-2xl font-semibold text-center">Visualize Data</h2>
57
- <p class="text-base text-center text-gray-300">Create charts from Excel or CSV files.</p>
58
- </div>
59
- </div>
60
- </div>
61
-
62
- <!-- Modals -->
63
- <!-- Summarize Modal -->
64
- <div id="summarize-modal" class="modal hidden">
65
- <div class="modal-content">
66
- <span class="close-modal">×</span>
67
- <h2 class="text-2xl font-semibold mb-4 cosmic-gradient">Summarize Text</h2>
68
- <div class="flex mb-4">
69
- <button class="tab-btn active" data-tab="summarize-text">Text</button>
70
- <button class="tab-btn" data-tab="summarize-file">File</button>
71
- </div>
72
- <form id="summarize-form" class="tab-content" data-tab="summarize-text">
73
- <div class="input-bar">
74
- <input type="text" class="w-full p-3 bg-gray-800 bg-opacity-50 rounded" placeholder="Enter text to summarize..." required>
75
- <button type="submit" class="cosmic-btn ml-2">Send</button>
76
- </div>
77
- <div class="loading-spinner hidden">Processing your request...</div>
78
- </form>
79
- <form id="summarize-file-form" class="tab-content hidden" data-tab="summarize-file">
80
- <div class="drop-area" ondragover="event.preventDefault();" ondrop="handleDrop(event, this)" onclick="this.querySelector('input').click();">
81
- <p>Drop File Here or Click to Choose</p>
82
- <input type="file" accept=".pdf,.docx,.txt,.rtf" class="hidden">
83
- </div>
84
- <button type="submit" class="cosmic-btn mt-4">Send</button>
85
- <div class="loading-spinner hidden">Processing your request...</div>
86
- </form>
87
- <div id="summarize-response" class="response-card hidden"></div>
88
- </div>
89
- </div>
90
- <!-- Translate Modal -->
91
- <div id="translate-modal" class="modal hidden">
92
- <div class="modal-content">
93
- <span class="close-modal">×</span>
94
- <h2 class="text-2xl font-semibold mb-4 cosmic-gradient">Translate</h2>
95
- <div class="flex mb-4">
96
- <button class="tab-btn active" data-tab="translate-text">Text</button>
97
- <button class="tab-btn" data-tab="translate-file">File</button>
98
- </div>
99
- <form id="translate-text-form" class="tab-content" data-tab="translate-text">
100
- <div class="input-bar">
101
- <input type="text" class="w-full p-3 bg-gray-800 bg-opacity-50 rounded" placeholder="Enter text to translate..." required>
102
- <button type="submit" class="cosmic-btn ml-2">Send</button>
103
- </div>
104
- <select class="w-full p-3 mt-3 bg-gray-800 bg-opacity-50 rounded" name="language">
105
- <option value="english">English</option>
106
- <option value="french">French</option>
107
- <option value="spanish">Spanish</option>
108
- <option value="german">German</option>
109
- <option value="italian">Italian</option>
110
- <option value="russian">Russian</option>
111
- <option value="chinese">Chinese</option>
112
- <option value="japanese">Japanese</option>
113
- <option value="arabic">Arabic</option>
114
- <option value="hindi">Hindi</option>
115
- <option value="portuguese">Portuguese</option>
116
- <option value="korean">Korean</option>
117
- </select>
118
- <div class="loading-spinner hidden">Processing your request...</div>
119
- </form>
120
- <form id="translate-file-form" class="tab-content hidden" data-tab="translate-file">
121
- <div class="drop-area" ondragover="event.preventDefault();" ondrop="handleDrop(event, this)" onclick="this.querySelector('input').click();">
122
- <p>Drop File Here or Click to Choose</p>
123
- <input type="file" accept=".pdf,.docx,.txt,.rtf" class="hidden">
124
- </div>
125
- <select class="w-full p-3 mt-3 bg-gray-800 bg-opacity-50 rounded" name="language">
126
- <option value="english">English</option>
127
- <option value="french">French</option>
128
- <option value="spanish">Spanish</option>
129
- <option value="german">German</option>
130
- <option value="italian">Italian</option>
131
- <option value="russian">Russian</option>
132
- <option value="chinese">Chinese</option>
133
- <option value="japanese">Japanese</option>
134
- <option value="arabic">Arabic</option>
135
- <option value="hindi">Hindi</option>
136
- <option value="portuguese">Portuguese</option>
137
- <option value="korean">Korean</option>
138
- </select>
139
- <button type="submit" class="cosmic-btn mt-4">Send</button>
140
- <div class="loading-spinner hidden">Processing your request...</div>
141
- </form>
142
- <div id="translate-response" class="response-card hidden"></div>
143
- </div>
144
- </div>
145
- <!-- File QA Modal -->
146
- <div id="file-qa-modal" class="modal hidden">
147
- <div class="modal-content">
148
- <span class="close-modal">×</span>
149
- <h2 class="text-2xl font-semibold mb-4 cosmic-gradient">Ask About File</h2>
150
- <form id="file-qa-form">
151
- <div class="drop-area" ondragover="event.preventDefault();" ondrop="handleDrop(event, this)" onclick="this.querySelector('input').click();">
152
- <p>Drop File Here or Click to Choose</p>
153
- <input type="file" accept=".pdf,.docx,.txt,.rtf" class="hidden">
154
- </div>
155
- <div class="input-bar mt-3">
156
- <input type="text" class="w-full p-3 bg-gray-800 bg-opacity-50 rounded" placeholder="Ask a question about the file..." required>
157
- <button type="submit" class="cosmic-btn ml-2">Send</button>
158
- </div>
159
- <div class="loading-spinner hidden">Processing your request...</div>
160
- </form>
161
- <div id="file-qa-response" class="response-card hidden"></div>
162
- </div>
163
- </div>
164
- <!-- Image Caption Modal -->
165
- <div id="image-caption-modal" class="modal hidden">
166
- <div class="modal-content">
167
- <span class="close-modal">×</span>
168
- <h2 class="text-2xl font-semibold mb-4 cosmic-gradient">Image Caption</h2>
169
- <form id="image-caption-form">
170
- <div class="drop-area" ondragover="event.preventDefault();" ondrop="handleDrop(event, this)" onclick="this.querySelector('input').click();">
171
- <p>Drop Image Here or Click to Choose</p>
172
- <input type="file" accept="image/*" class="hidden">
173
- </div>
174
- <button type="submit" class="cosmic-btn mt-4">Send</button>
175
- <div class="loading-spinner hidden">Processing your request...</div>
176
- </form>
177
- <div id="image-caption-response" class="response-card hidden"></div>
178
- </div>
179
- </div>
180
- <!-- Visual QA Modal -->
181
- <div id="visual-qa-modal" class="modal hidden">
182
- <div class="modal-content">
183
- <span class="close-modal">×</span>
184
- <h2 class="text-2xl font-semibold mb-4 cosmic-gradient">Image Questions</h2>
185
- <form id="visual-qa-form">
186
- <div class="drop-area" ondragover="event.preventDefault();" ondrop="handleDrop(event, this)" onclick="this.querySelector('input').click();">
187
- <p>Drop Image Here or Click to Choose</p>
188
- <input type="file" accept="image/*" class="hidden">
189
- </div>
190
- <div class="input-bar mt-3">
191
- <input type="text" class="w-full p-3 bg-gray-800 bg-opacity-50 rounded" placeholder="Ask a question about the image..." required>
192
- <button type="submit" class="cosmic-btn ml-2">Send</button>
193
- </div>
194
- <div class="loading-spinner hidden">Processing your request...</div>
195
- </form>
196
- <div id="visual-qa-response" class="response-card hidden"></div>
197
- </div>
198
- </div>
199
- <!-- Visualize Modal -->
200
- <div id="visualize-modal" class="modal hidden">
201
- <div class="modal-content">
202
- <span class="close-modal">×</span>
203
- <h2 class="text-2xl font-semibold mb-4 cosmic-gradient">Visualize Data</h2>
204
- <form id="visualize-form">
205
- <div class="drop-area" ondragover="event.preventDefault();" ondrop="handleDrop(event, this)" onclick="this.querySelector('input').click();">
206
- <p>Drop File Here or Click to Choose</p>
207
- <input type="file" accept=".csv,.xlsx,.xls" class="hidden">
208
- </div>
209
- <select class="w-full p-3 mt-3 bg-gray-800 bg-opacity-50 rounded" name="visualization-type">
210
- <option value="scatter">Scatter Plot</option>
211
- <option value="bar">Bar Chart</option>
212
- <option value="histogram">Histogram</option>
213
- <option value="dashboard">Dashboard</option>
214
- </select>
215
- <button type="submit" class="cosmic-btn mt-4">Send</button>
216
- <div class="loading-spinner hidden">Processing your request...</div>
217
- </form>
218
- <div id="visualize-response" class="response-card hidden"></div>
219
- </div>
220
- </div>
221
- <!-- Chatbot Modal -->
222
- <div id="chatbot-modal" class="modal hidden">
223
- <div class="modal-content chatbot-modal">
224
- <span class="close-modal">×</span>
225
- <h2 class="text-2xl font-semibold mb-4 cosmic-gradient">Gemini Chatbot</h2>
226
- <div id="chatbot-conversation" class="chatbot-conversation"></div>
227
- <form id="chatbot-form">
228
- <div class="input-bar">
229
- <input type="text" class="w-full p-3 bg-gray-800 bg-opacity-50 rounded" placeholder="Type your message..." required>
230
- <button type="submit" class="cosmic-btn ml-2">Send</button>
231
- </div>
232
- <div class="loading-spinner hidden">Processing your request...</div>
233
- </form>
234
- </div>
235
- </div>
236
-
237
- <script src="/static/scripts.js"></script>
238
- <script>(function(){function c(){var b=a.contentDocument||a.contentWindow.document;if(b){var d=b.createElement('script');d.innerHTML="window.__CF$cv$params={r:'9380a9673b566733',t:'MTc0NTk0OTIzNi4wMDAwMDA='};var a=document.createElement('script');a.nonce='';a.src='/cdn-cgi/challenge-platform/scripts/jsd/main.js';document.getElementsByTagName('head')[0].appendChild(a);";b.getElementsByTagName('head')[0].appendChild(d)}}if(document.body){var a=document.createElement('iframe');a.height=1;a.width=1;a.style.position='absolute';a.style.top=0;a.style.left=0;a.style.border='none';a.style.visibility='hidden';document.body.appendChild(a);if('loading'!==document.readyState)c();else if(window.addEventListener)document.addEventListener('DOMContentLoaded',c);else{var e=document.onreadystatechange||function(){};document.onreadystatechange=function(b){e(b);'loading'!==document.readyState&&(document.onreadystatechange=e,c())}}}})();</script></body>
239
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ```javascript
2
+ document.addEventListener('DOMContentLoaded', () => {
3
+ // Starry Background Animation
4
+ const stars = document.createElement('canvas');
5
+ stars.className = 'stars';
6
+ document.body.appendChild(stars);
7
+ const ctx = stars.getContext('2d');
8
+ stars.width = window.innerWidth;
9
+ stars.height = window.innerHeight;
10
+ const starArray = [];
11
+ for (let i = 0; i < 100; i++) {
12
+ starArray.push({
13
+ x: Math.random() * stars.width,
14
+ y: Math.random() * stars.height,
15
+ radius: Math.random() * 2,
16
+ opacity: Math.random()
17
+ });
18
+ }
19
+ function animateStars() {
20
+ ctx.clearRect(0, 0, stars.width, stars.height);
21
+ starArray.forEach(star => {
22
+ ctx.beginPath();
23
+ ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2);
24
+ ctx.fillStyle = `rgba(255, 255, 255, ${star.opacity})`;
25
+ ctx.fill();
26
+ star.opacity += (Math.random() - 0.5) * 0.05;
27
+ if (star.opacity > 1) star.opacity = 1;
28
+ if (star.opacity < 0) star.opacity = 0;
29
+ });
30
+ requestAnimationFrame(animateStars);
31
+ }
32
+ animateStars();
33
+
34
+ // Card Hover Effects
35
+ const cards = document.querySelectorAll(".card");
36
+ cards.forEach(card => {
37
+ card.addEventListener("mouseenter", () => {
38
+ if (!card.classList.contains('shadowed')) {
39
+ card.style.transition = "transform 0.4s ease-in-out";
40
+ card.style.transform = "scale(1.05) rotate(0.5deg)";
41
+ }
42
+ });
43
+ card.addEventListener("mouseleave", () => {
44
+ if (!card.classList.contains('shadowed')) {
45
+ card.style.transform = "scale(1) rotate(0deg)";
46
+ }
47
+ });
48
+ });
49
+
50
+ // Window Resize Handler for Canvas
51
+ window.addEventListener('resize', () => {
52
+ stars.width = window.innerWidth;
53
+ stars.height = window.innerHeight;
54
+ starArray.length = 0;
55
+ for (let i = 0; i < 100; i++) {
56
+ starArray.push({
57
+ x: Math.random() * stars.width,
58
+ y: Math.random() * stars.height,
59
+ radius: Math.random() * 2,
60
+ opacity: Math.random()
61
+ });
62
+ }
63
+ });
64
+
65
+ // Box Click to Open Modal
66
+ document.querySelectorAll('.function-box').forEach(box => {
67
+ box.addEventListener('click', () => {
68
+ const modalId = box.dataset.modal;
69
+ document.getElementById(modalId).classList.remove('hidden');
70
+ // Dim other function-box elements
71
+ document.querySelectorAll('.function-box').forEach(otherBox => {
72
+ if (otherBox !== box) {
73
+ otherBox.classList.add('shadowed');
74
+ }
75
+ });
76
+ });
77
+ });
78
+
79
+ // Chatbot Icon Click
80
+ document.querySelector('.chatbot-icon').addEventListener('click', () => {
81
+ document.getElementById('chatbot-modal').classList.remove('hidden');
82
+ });
83
+
84
+ // Close Modal
85
+ document.querySelectorAll('.close-modal').forEach(closeBtn => {
86
+ closeBtn.addEventListener('click', () => {
87
+ closeBtn.closest('.modal').classList.add('hidden');
88
+ // Reset forms and responses
89
+ const forms = closeBtn.closest('.modal').querySelectorAll('form');
90
+ forms.forEach(form => {
91
+ form.reset();
92
+ // Restaurer l'état des boutons
93
+ const submitButton = form.querySelector('button[type="submit"]');
94
+ if (submitButton) {
95
+ submitButton.classList.remove('loading');
96
+ submitButton.innerHTML = 'Send';
97
+ submitButton.disabled = false;
98
+ }
99
+ });
100
+ const responseCards = closeBtn.closest('.modal').querySelectorAll('.response-card');
101
+ responseCards.forEach(card => {
102
+ card.classList.add('hidden');
103
+ card.innerHTML = '';
104
+ });
105
+ const dropAreas = closeBtn.closest('.modal').querySelectorAll('.drop-area p');
106
+ dropAreas.forEach(p => p.textContent = 'Drop File Here or Click to Choose');
107
+ // Clear chatbot conversation
108
+ if (closeBtn.closest('.modal').id === 'chatbot-modal') {
109
+ document.getElementById('chatbot-conversation').innerHTML = '';
110
+ }
111
+ // Remove dimming from all function-box elements
112
+ document.querySelectorAll('.function-box').forEach(box => {
113
+ box.classList.remove('shadowed');
114
+ });
115
+ });
116
+ });
117
+
118
+ // Tab Switching for Summarize and Translate
119
+ document.querySelectorAll('.tab-btn').forEach(btn => {
120
+ btn.addEventListener('click', () => {
121
+ const tab = btn.dataset.tab;
122
+ btn.closest('.modal').querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
123
+ btn.classList.add('active');
124
+ btn.closest('.modal').querySelectorAll('.tab-content').forEach(content => {
125
+ content.classList.add('hidden');
126
+ if (content.dataset.tab === tab) content.classList.remove('hidden');
127
+ });
128
+ });
129
+ });
130
+
131
+ // File Drop Handler
132
+ window.handleDrop = function(event, dropArea) {
133
+ event.preventDefault();
134
+ const fileInput = dropArea.querySelector('input[type="file"]');
135
+ const files = event.dataTransfer.files;
136
+ if (files.length > 0) {
137
+ fileInput.files = files;
138
+ dropArea.querySelector('p').textContent = `Selected: ${files[0].name}`;
139
+ }
140
+ };
141
+
142
+ // Chatbot Form Submission
143
+ document.getElementById('chatbot-form').addEventListener('submit', async (e) => {
144
+ e.preventDefault();
145
+ const input = e.target.querySelector('input');
146
+ const message = input.value.trim();
147
+ const submitButton = e.target.querySelector('button[type="submit"]');
148
+ if (!message) return;
149
+
150
+ // Mettre le bouton en mode chargement
151
+ submitButton.classList.add('loading');
152
+ submitButton.innerHTML = '<span class="spinner"></span>Loading...';
153
+ submitButton.disabled = true;
154
+
155
+ const conversation = document.getElementById('chatbot-conversation');
156
+ conversation.innerHTML += `<p class="user-message">You: ${message}</p>`;
157
+ conversation.scrollTop = conversation.scrollHeight;
158
+ input.value = '';
159
+
160
+ try {
161
+ const response = await fetch('/chat', {
162
+ method: 'POST',
163
+ headers: { 'Content-Type': 'application/json' },
164
+ body: JSON.stringify({ message })
165
+ });
166
+ const data = await response.json();
167
+ // Restaurer le bouton
168
+ submitButton.classList.remove('loading');
169
+ submitButton.innerHTML = 'Send';
170
+ submitButton.disabled = false;
171
+
172
+ if (response.ok) {
173
+ conversation.innerHTML += `<p class="bot-message">Gemini: ${data.response}</p>`;
174
+ } else {
175
+ conversation.innerHTML += `<p class="bot-message">Error: ${data.detail}</p>`;
176
+ }
177
+ conversation.scrollTop = conversation.scrollHeight;
178
+ } catch (error) {
179
+ // Restaurer le bouton en cas d'erreur
180
+ submitButton.classList.remove('loading');
181
+ submitButton.innerHTML = 'Send';
182
+ submitButton.disabled = false;
183
+ conversation.innerHTML += `<p class="bot-message">Error: ${error.message}</p>`;
184
+ conversation.scrollTop = conversation.scrollHeight;
185
+ }
186
+ });
187
+
188
+ // Form Submissions for Other Functionalities
189
+ const forms = {
190
+ 'summarize-form': { endpoint: '/process', intent: 'summarize' },
191
+ 'summarize-file-form': { endpoint: '/process', intent: 'summarize' },
192
+ 'translate-text-form': { endpoint: '/process', intent: 'translate' },
193
+ 'translate-file-form': { endpoint: '/process', intent: 'file-translate' },
194
+ 'file-qa-form': { endpoint: '/process', intent: 'file-qa' },
195
+ 'image-caption-form': { endpoint: '/process', intent: 'image-to-text' },
196
+ 'visual-qa-form': { endpoint: '/process', intent: 'visual-qa' },
197
+ 'visualize-form': { endpoint: '/process', intent: 'visualize' }
198
+ };
199
+
200
+ Object.keys(forms).forEach(formId => {
201
+ const form = document.getElementById(formId);
202
+ form.addEventListener('submit', async (e) => {
203
+ e.preventDefault();
204
+ const formData = new FormData();
205
+ const responseCard = form.nextElementSibling;
206
+ const submitButton = form.querySelector('button[type="submit"]');
207
+ responseCard.classList.add('hidden');
208
+ responseCard.innerHTML = '';
209
+
210
+ // Mettre le bouton en mode chargement
211
+ submitButton.classList.add('loading');
212
+ submitButton.innerHTML = '<span class="spinner"></span>Loading...';
213
+ submitButton.disabled = true;
214
+
215
+ try {
216
+ // Préparer les données du formulaire
217
+ if (formId === 'summarize-form') {
218
+ formData.append('text', form.querySelector('input[type="text"]').value);
219
+ } else if (formId === 'summarize-file-form') {
220
+ const file = form.querySelector('input[type="file"]').files[0];
221
+ if (!file) {
222
+ responseCard.innerHTML = `<p class="text-red-500">Please select a file.</p>`;
223
+ responseCard.classList.remove('hidden');
224
+ submitButton.classList.remove('loading');
225
+ submitButton.innerHTML = 'Send';
226
+ submitButton.disabled = false;
227
+ return;
228
+ }
229
+ formData.append('file', file);
230
+ } else if (formId === 'translate-text-form') {
231
+ const text = form.querySelector('input[type="text"]').value;
232
+ const lang = form.querySelector('select[name="language"]').value;
233
+ formData.append('text', `Translate to ${lang}: ${text}`);
234
+ } else if (formId === 'translate-file-form') {
235
+ const file = form.querySelector('input[type="file"]').files[0];
236
+ const lang = form.querySelector('select[name="language"]').value;
237
+ if (!file) {
238
+ responseCard.innerHTML = `<p class="text-red-500">Please select a file.</p>`;
239
+ responseCard.classList.remove('hidden');
240
+ submitButton.classList.remove('loading');
241
+ submitButton.innerHTML = 'Send';
242
+ submitButton.disabled = false;
243
+ return;
244
+ }
245
+ formData.append('file', file);
246
+ formData.append('text', `Translate to ${lang}`);
247
+ } else if (formId === 'file-qa-form') {
248
+ const file = form.querySelector('input[type="file"]').files[0];
249
+ const text = form.querySelector('input[type="text"]').value;
250
+ if (!file) {
251
+ responseCard.innerHTML = `<p class="text-red-500">Please select a file.</p>`;
252
+ responseCard.classList.remove('hidden');
253
+ submitButton.classList.remove('loading');
254
+ submitButton.innerHTML = 'Send';
255
+ submitButton.disabled = false;
256
+ return;
257
+ }
258
+ formData.append('file', file);
259
+ formData.append('text', text);
260
+ } else if (formId === 'image-caption-form') {
261
+ const file = form.querySelector('input[type="file"]').files[0];
262
+ if (!file) {
263
+ responseCard.innerHTML = `<p class="text-red-500">Please select an image.</p>`;
264
+ responseCard.classList.remove('hidden');
265
+ submitButton.classList.remove('loading');
266
+ submitButton.innerHTML = 'Send';
267
+ submitButton.disabled = false;
268
+ return;
269
+ }
270
+ formData.append('file', file);
271
+ } else if (formId === 'visual-qa-form') {
272
+ const file = form.querySelector('input[type="file"]').files[0];
273
+ const text = form.querySelector('input[type="text"]').value;
274
+ if (!file) {
275
+ responseCard.innerHTML = `<p class="text-red-500">Please select an image.</p>`;
276
+ responseCard.classList.remove('hidden');
277
+ submitButton.classList.remove('loading');
278
+ submitButton.innerHTML = 'Send';
279
+ submitButton.disabled = false;
280
+ return;
281
+ }
282
+ formData.append('file', file);
283
+ formData.append('text', text);
284
+ } else if (formId === 'visualize-form') {
285
+ const file = form.querySelector('input[type="file"]').files[0];
286
+ const visualizationType = form.querySelector('select[name="visualization-type"]').value;
287
+ if (!file) {
288
+ responseCard.innerHTML = `<p class="text-red-500">Please select a file.</p>`;
289
+ responseCard.classList.remove('hidden');
290
+ submitButton.classList.remove('loading');
291
+ submitButton.innerHTML = 'Send';
292
+ submitButton.disabled = false;
293
+ return;
294
+ }
295
+ formData.append('file', file);
296
+ formData.append('text', visualizationType);
297
+ }
298
+
299
+ // Envoyer la requête
300
+ const response = await fetch(forms[formId].endpoint, {
301
+ method: 'POST',
302
+ body: formData
303
+ });
304
+ const data = await response.json();
305
+
306
+ // Restaurer le bouton
307
+ submitButton.classList.remove('loading');
308
+ submitButton.innerHTML = 'Send';
309
+ submitButton.disabled = false;
310
+
311
+ // Afficher la réponse
312
+ if (response.ok) {
313
+ // Cas spécial pour image-caption et visual-qa
314
+ if (formId === 'image-caption-form' && data.additional_data && data.additional_data.image_url) {
315
+ responseCard.innerHTML = `
316
+ <img src="${data.additional_data.image_url}" alt="Uploaded Image" class="response-image">
317
+ <p><strong>Caption:</strong> ${data.response}</p>
318
+ `;
319
+ } else if (formId === 'visual-qa-form' && data.additional_data && data.additional_data.image_url && data.additional_data.question) {
320
+ responseCard.innerHTML = `
321
+ <img src="${data.additional_data.image_url}" alt="Uploaded Image" class="response-image">
322
+ <p><strong>Question:</strong> ${data.additional_data.question}</p>
323
+ <p><strong>Answer:</strong> ${data.response}</p>
324
+ `;
325
+ } else {
326
+ // Cas général pour les autres formulaires
327
+ responseCard.innerHTML = `<p>${data.response}</p>`;
328
+ if (data.additional_data) {
329
+ Object.entries(data.additional_data).forEach(([key, value]) => {
330
+ // Ignorer image_url pour les autres formulaires
331
+ if (key !== 'image_url') {
332
+ responseCard.innerHTML += `<p><strong>${key.replace('_', ' ').replace(/\b\w/g, char => char.toUpperCase())}:</strong> ${value}</p>`;
333
+ }
334
+ });
335
+ }
336
+ }
337
+ responseCard.classList.remove('hidden');
338
+ } else {
339
+ responseCard.innerHTML = `<p class="text-red-500">Error: ${data.detail}</p>`;
340
+ responseCard.classList.remove('hidden');
341
+ }
342
+ } catch (error) {
343
+ // Restaurer le bouton en cas d'erreur
344
+ submitButton.classList.remove('loading');
345
+ submitButton.innerHTML = 'Send';
346
+ submitButton.disabled = false;
347
+ responseCard.innerHTML = `<p class="text-red-500">Error: ${error.message}</p>`;
348
+ responseCard.classList.remove('hidden');
349
+ }
350
+ });
351
+ });
352
+ });
353
+ ```