Docfile commited on
Commit
7b5b5f3
·
verified ·
1 Parent(s): 7b526d8

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +202 -77
templates/index.html CHANGED
@@ -186,23 +186,66 @@
186
  .message-bubble:hover .copy-btn {
187
  opacity: 1;
188
  }
 
189
  .file-preview {
190
- max-width: 300px;
191
- margin: 0.5rem auto;
192
- position: relative;
193
- overflow: hidden;
194
- border-radius: 0.5rem;
195
- transition: transform 0.2s ease;
 
196
  }
197
- .file-preview:hover {
198
- transform: scale(1.02);
199
  }
200
- .file-preview img {
201
- width: 100%;
202
- height: auto;
203
- display: block;
204
- object-fit: cover;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
205
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
206
  .chip {
207
  display: inline-flex;
208
  align-items: center;
@@ -416,6 +459,17 @@
416
  #send-button i {
417
  font-size: 0.9rem;
418
  }
 
 
 
 
 
 
 
 
 
 
 
419
  }
420
  /* Container pour le textarea et le bouton */
421
  .input-wrapper {
@@ -497,7 +551,7 @@
497
  </div>
498
  <!-- Zone de prévisualisation -->
499
  <div id="preview-area" class="px-4 py-2 bg-gray-50 dark:bg-gray-800/50 hidden">
500
- <div id="file-preview" class="hidden"></div>
501
  </div>
502
  <!-- Barre d'options -->
503
  <div class="flex items-center justify-between flex-wrap gap-y-2 px-4 py-2 bg-gray-100 dark:bg-gray-800/80 text-sm text-gray-600 dark:text-gray-300">
@@ -523,23 +577,22 @@
523
  <span class="tooltip-text">Raisonnement avancé (1 fois/min)</span>
524
  </label>
525
  </div>
 
526
  <div class="flex items-center space-x-2">
527
-
528
-
529
  <label for="file_upload" class="cursor-pointer flex items-center text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 tooltip">
530
- <i class="fa-solid fa-paperclip"></i>
531
- <span class="ml-1.5 hidden sm:inline">Fichiers</span>
532
- <input type="file" id="file_upload" name="file[]" class="hidden" accept=".txt,.pdf,.png,.jpg,.jpeg" multiple>
533
- <span class="tooltip-text">Joindre plusieurs fichiers (txt, pdf, image)</span>
534
- </label>
535
 
536
-
537
  <div id="file-chip" class="chip hidden">
538
- <i class="fa-solid fa-file chip-icon"></i>
539
  <span id="file-name" class="truncate max-w-[100px] sm:max-w-[120px]"></span>
540
  <i id="clear-file" class="fa-solid fa-xmark chip-close"></i>
541
  </div>
542
  </div>
 
543
  </div>
544
  <!-- Formulaire de chat -->
545
  <form id="chat-form" class="p-3 sm:p-4 bg-white dark:bg-gray-900">
@@ -604,6 +657,7 @@
604
  const MOBILE_BREAKPOINT = 640;
605
  let advancedToggleCooldownEndTime = 0;
606
  let isComposing = false;
 
607
 
608
  // Gestion du thème
609
  function initializeTheme() {
@@ -757,12 +811,13 @@
757
  scrollToBottom();
758
  }
759
  function escapeHtml(unsafe) {
 
760
  return unsafe
761
- .replace(/&/g, "&amp;")
762
- .replace(/</g, "&lt;")
763
- .replace(/>/g, "&gt;")
764
- .replace(/"/g, "&quot;")
765
- .replace(/'/g, "&#039;");
766
  }
767
 
768
  // Gestion du cooldown pour le raisonnement avancé
@@ -829,55 +884,97 @@
829
  }
830
  }
831
 
832
- // Gestion des fichiers
833
  function clearFileInput() {
834
- fileUpload.value = '';
835
  fileChip.classList.add('hidden');
836
  fileNameSpan.textContent = '';
837
  fileNameSpan.title = '';
838
- filePreview.innerHTML = '';
839
  filePreview.classList.add('hidden');
840
  previewArea.classList.add('hidden');
 
841
  }
 
 
 
842
  fileUpload.addEventListener('change', () => {
843
  if (fileUpload.files.length > 0) {
844
- const file = fileUpload.files[0];
845
- const name = file.name;
846
- fileNameSpan.textContent = name;
847
- fileNameSpan.title = name;
848
- fileChip.classList.remove('hidden');
849
  filePreview.innerHTML = '';
850
- if (file.type.startsWith('image/')) {
851
- const reader = new FileReader();
852
- reader.onload = (e) => {
853
- filePreview.innerHTML = `
854
- <div class="file-preview">
855
- <img src="${e.target.result}" alt="Prévisualisation: ${escapeHtml(name)}">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
856
  </div>`;
857
- filePreview.classList.remove('hidden');
858
- previewArea.classList.remove('hidden');
859
- };
860
- reader.onerror = () => {
861
- filePreview.innerHTML = `<p class="text-red-500 text-xs text-center p-2">Erreur lecture image</p>`;
862
- filePreview.classList.remove('hidden');
863
- previewArea.classList.remove('hidden');
864
- };
865
- reader.readAsDataURL(file);
866
- } else {
867
- filePreview.innerHTML = `
868
- <div class="flex items-center justify-center p-3">
869
- <div class="bg-gray-100 dark:bg-gray-800 p-3 rounded-lg text-center">
870
- <i class="fa-solid ${getFileIcon(file.type)} text-3xl text-gray-500 dark:text-gray-400 mb-2"></i>
871
- <p class="text-xs text-gray-500 dark:text-gray-400">${formatFileSize(file.size)}</p>
872
- </div>
873
- </div>`;
874
- filePreview.classList.remove('hidden');
875
- previewArea.classList.remove('hidden');
876
  }
 
 
 
877
  } else {
878
  clearFileInput();
879
  }
880
  });
 
 
881
  function getFileIcon(fileType) {
882
  if (!fileType) return 'fa-file';
883
  if (fileType.includes('pdf')) return 'fa-file-pdf';
@@ -905,14 +1002,16 @@
905
  setTimeout(() => adjustTextareaHeight(promptInput), 0);
906
  } else if (!isMobile && !e.shiftKey) {
907
  e.preventDefault();
908
- if (!sendButton.disabled && (promptInput.value.trim() || fileUpload.files.length > 0)) {
 
909
  chatForm.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
910
  }
911
  } else if (e.shiftKey) {
912
  setTimeout(() => adjustTextareaHeight(promptInput), 0);
913
  if (isMobile) {
914
  e.preventDefault();
915
- if (!sendButton.disabled && (promptInput.value.trim() || fileUpload.files.length > 0)) {
 
916
  chatForm.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
917
  }
918
  }
@@ -926,19 +1025,23 @@
926
  });
927
  adjustTextareaHeight(promptInput);
928
 
929
- // Soumission du formulaire
930
  chatForm.addEventListener('submit', async (e) => {
931
  e.preventDefault();
932
  const prompt = promptInput.value.trim();
933
- const file = fileUpload.files[0];
934
  const useWebSearch = webSearchToggle.checked;
935
  const useAdvanced = advancedToggle.checked;
 
936
  if (sendButton.disabled) return;
937
- if (!prompt && !file) {
 
938
  promptInput.focus();
939
  return;
940
  }
 
941
  errorMessageDiv.classList.add('hidden');
 
 
942
  if (useAdvanced) {
943
  const now = Date.now();
944
  if (advancedToggleCooldownEndTime > 0 && now < advancedToggleCooldownEndTime) {
@@ -947,37 +1050,57 @@
947
  return;
948
  }
949
  }
 
 
950
  let userMessageText = prompt;
951
- if (file && file.name) {
952
- userMessageText = prompt ? `${prompt}\n[Fichier: ${file.name}]` : `[Fichier joint: ${file.name}]`;
 
 
 
 
 
953
  }
 
954
  addMessageToChat('user', userMessageText);
 
 
955
  const formData = new FormData();
956
  formData.append('prompt', prompt);
957
  formData.append('web_search', useWebSearch);
958
  formData.append('advanced_reasoning', useAdvanced);
959
- if (file) {
960
- formData.append('file', file);
961
- }
 
 
 
 
962
  promptInput.value = '';
963
  adjustTextareaHeight(promptInput);
964
- clearFileInput();
 
965
  if (useAdvanced) {
966
  startAdvancedCooldownTimer();
967
  advancedToggle.checked = false;
968
  }
969
  webSearchToggle.checked = false;
970
  showLoading(true);
 
 
971
  try {
972
  const response = await fetch(API_CHAT_ENDPOINT, { method: 'POST', body: formData });
973
  const data = await response.json();
974
  if (!response.ok) {
975
- throw new Error(data.error || `Erreur serveur: ${response.status} ${response.statusText}`);
976
  }
977
  if (data.success && data.message) {
978
  addMessageToChat('assistant', data.message, true);
979
- } else {
980
- throw new Error(data.error || "Réponse invalide ou vide du serveur.");
 
 
 
981
  }
982
  } catch (error) {
983
  console.error("Chat Error:", error);
@@ -987,6 +1110,7 @@
987
  promptInput.focus();
988
  }
989
  });
 
990
 
991
  // Effacement de la conversation
992
  clearForm.addEventListener('submit', async (e) => {
@@ -1021,7 +1145,7 @@
1021
  clearButton.disabled = true;
1022
  clearButton.innerHTML = '<i class="fa-solid fa-spinner fa-spin mr-1.5"></i><span class="hidden sm:inline">Effacement...</span>';
1023
  try {
1024
- const response = await fetch(CLEAR_ENDPOINT, {
1025
  method: 'POST',
1026
  headers: {
1027
  'X-Requested-With': 'XMLHttpRequest'
@@ -1033,6 +1157,7 @@
1033
  messagesToRemove.forEach(el => el.remove());
1034
  addMessageToChat('assistant', "Conversation effacée. Comment puis-je vous aider maintenant ?", true);
1035
  errorMessageDiv.classList.add('hidden');
 
1036
  } else {
1037
  throw new Error(data.error || "Impossible d'effacer la conversation.");
1038
  }
@@ -1093,4 +1218,4 @@
1093
  });
1094
  </script>
1095
  </body>
1096
- </html>
 
186
  .message-bubble:hover .copy-btn {
187
  opacity: 1;
188
  }
189
+ /* START: CSS for multi-file preview */
190
  .file-preview {
191
+ max-height: 200px; /* Adjusted max-height for multi previews */
192
+ overflow-y: auto;
193
+ scrollbar-width: thin;
194
+ padding: 0.5rem; /* Add some padding */
195
+ background-color: rgba(243, 244, 246, 0.5); /* Light background */
196
+ border-radius: 0.5rem;
197
+ margin-top: 0.5rem;
198
  }
199
+ .dark .file-preview {
200
+ background-color: rgba(30, 41, 59, 0.5); /* Darker background for dark mode */
201
  }
202
+
203
+ .file-preview-item {
204
+ background-color: rgba(255, 255, 255, 0.7);
205
+ transition: all 0.2s ease-in-out;
206
+ margin-bottom: 0.5rem;
207
+ padding: 0.5rem;
208
+ border: 1px solid #e5e7eb;
209
+ border-radius: 0.375rem;
210
+ display: flex;
211
+ align-items: center;
212
+ }
213
+
214
+ .dark .file-preview-item {
215
+ background-color: rgba(51, 65, 85, 0.5);
216
+ border-color: rgba(71, 85, 105, 0.5);
217
+ }
218
+
219
+ .file-preview-item:hover {
220
+ background-color: rgba(255, 255, 255, 1);
221
+ }
222
+
223
+ .dark .file-preview-item:hover {
224
+ background-color: rgba(51, 65, 85, 0.8);
225
+ }
226
+
227
+ #file-preview::-webkit-scrollbar {
228
+ width: 5px;
229
  }
230
+
231
+ #file-preview::-webkit-scrollbar-thumb {
232
+ background-color: rgba(156, 163, 175, 0.5);
233
+ border-radius: 3px;
234
+ }
235
+
236
+ #file-preview::-webkit-scrollbar-track {
237
+ background-color: rgba(229, 231, 235, 0.3);
238
+ }
239
+
240
+ .dark #file-preview::-webkit-scrollbar-thumb {
241
+ background-color: rgba(75, 85, 99, 0.5);
242
+ }
243
+
244
+ .dark #file-preview::-webkit-scrollbar-track {
245
+ background-color: rgba(31, 41, 55, 0.3);
246
+ }
247
+ /* END: CSS for multi-file preview */
248
+
249
  .chip {
250
  display: inline-flex;
251
  align-items: center;
 
459
  #send-button i {
460
  font-size: 0.9rem;
461
  }
462
+ /* Smaller file previews on mobile */
463
+ .file-preview-item {
464
+ padding: 0.375rem;
465
+ }
466
+ .file-preview-item .w-12 { width: 2.5rem; }
467
+ .file-preview-item .h-12 { height: 2.5rem; }
468
+ .file-preview-item .w-10 { width: 2rem; }
469
+ .file-preview-item .h-10 { height: 2rem; }
470
+ .file-preview-item .text-xs { font-size: 0.7rem; }
471
+ .file-preview { max-height: 150px; }
472
+
473
  }
474
  /* Container pour le textarea et le bouton */
475
  .input-wrapper {
 
551
  </div>
552
  <!-- Zone de prévisualisation -->
553
  <div id="preview-area" class="px-4 py-2 bg-gray-50 dark:bg-gray-800/50 hidden">
554
+ <div id="file-preview" class="hidden"></div> <!-- Container for multiple previews -->
555
  </div>
556
  <!-- Barre d'options -->
557
  <div class="flex items-center justify-between flex-wrap gap-y-2 px-4 py-2 bg-gray-100 dark:bg-gray-800/80 text-sm text-gray-600 dark:text-gray-300">
 
577
  <span class="tooltip-text">Raisonnement avancé (1 fois/min)</span>
578
  </label>
579
  </div>
580
+ <!-- START: Modified HTML for file input and chip -->
581
  <div class="flex items-center space-x-2">
 
 
582
  <label for="file_upload" class="cursor-pointer flex items-center text-primary-600 hover:text-primary-700 dark:text-primary-400 dark:hover:text-primary-300 tooltip">
583
+ <i class="fa-solid fa-paperclip"></i>
584
+ <span class="ml-1.5 hidden sm:inline">Fichiers</span>
585
+ <input type="file" id="file_upload" name="file[]" class="hidden" accept=".txt,.pdf,.png,.jpg,.jpeg" multiple>
586
+ <span class="tooltip-text">Joindre plusieurs fichiers (txt, pdf, image)</span>
587
+ </label>
588
 
 
589
  <div id="file-chip" class="chip hidden">
590
+ <i class="fa-solid fa-files chip-icon"></i> <!-- Changed icon to fa-files -->
591
  <span id="file-name" class="truncate max-w-[100px] sm:max-w-[120px]"></span>
592
  <i id="clear-file" class="fa-solid fa-xmark chip-close"></i>
593
  </div>
594
  </div>
595
+ <!-- END: Modified HTML for file input and chip -->
596
  </div>
597
  <!-- Formulaire de chat -->
598
  <form id="chat-form" class="p-3 sm:p-4 bg-white dark:bg-gray-900">
 
657
  const MOBILE_BREAKPOINT = 640;
658
  let advancedToggleCooldownEndTime = 0;
659
  let isComposing = false;
660
+ const filesList = []; // Pour stocker les fichiers sélectionnés
661
 
662
  // Gestion du thème
663
  function initializeTheme() {
 
811
  scrollToBottom();
812
  }
813
  function escapeHtml(unsafe) {
814
+ if (typeof unsafe !== 'string') return '';
815
  return unsafe
816
+ .replace(/&/g, "&")
817
+ .replace(/</g, "<")
818
+ .replace(/>/g, ">")
819
+ .replace(/"/g, """)
820
+ .replace(/'/g, "'");
821
  }
822
 
823
  // Gestion du cooldown pour le raisonnement avancé
 
884
  }
885
  }
886
 
887
+ // START: Modified clearFileInput function
888
  function clearFileInput() {
889
+ fileUpload.value = ''; // Clear the input element
890
  fileChip.classList.add('hidden');
891
  fileNameSpan.textContent = '';
892
  fileNameSpan.title = '';
893
+ filePreview.innerHTML = ''; // Clear previews
894
  filePreview.classList.add('hidden');
895
  previewArea.classList.add('hidden');
896
+ filesList.length = 0; // Vider la liste des fichiers
897
  }
898
+ // END: Modified clearFileInput function
899
+
900
+ // START: Replaced fileUpload event listener for multiple files
901
  fileUpload.addEventListener('change', () => {
902
  if (fileUpload.files.length > 0) {
903
+ // Vider les prévisualisations précédentes et la liste
 
 
 
 
904
  filePreview.innerHTML = '';
905
+ fileChip.classList.add('hidden'); // Hide chip initially
906
+ filesList.length = 0;
907
+
908
+ // Mettre à jour la liste des fichiers
909
+ for (let i = 0; i < fileUpload.files.length; i++) {
910
+ filesList.push(fileUpload.files[i]);
911
+ }
912
+
913
+ // Afficher le nombre total de fichiers dans la puce
914
+ fileNameSpan.textContent = `${filesList.length} fichier${filesList.length > 1 ? 's' : ''}`;
915
+ fileNameSpan.title = filesList.map(f => f.name).join(', ');
916
+ fileChip.classList.remove('hidden');
917
+
918
+ // Créer des prévisualisations pour chaque fichier (jusqu'à un maximum raisonnable)
919
+ const maxPreviews = 5;
920
+ const filesToPreview = filesList.slice(0, maxPreviews);
921
+
922
+ filesToPreview.forEach(file => {
923
+ const previewItem = document.createElement('div');
924
+ // Added dark mode classes and adjusted structure
925
+ previewItem.className = 'file-preview-item mb-2 p-2 border rounded dark:border-gray-600 bg-white dark:bg-gray-700';
926
+
927
+ if (file.type.startsWith('image/')) {
928
+ const reader = new FileReader();
929
+ reader.onload = (e) => {
930
+ previewItem.innerHTML = `
931
+ <div class="flex items-center w-full">
932
+ <div class="w-12 h-12 flex-shrink-0 mr-2">
933
+ <img src="${e.target.result}" alt="Aperçu" class="h-full w-full object-cover rounded">
934
+ </div>
935
+ <div class="overflow-hidden flex-grow">
936
+ <p class="text-xs font-medium truncate text-gray-800 dark:text-gray-200">${escapeHtml(file.name)}</p>
937
+ <p class="text-xs text-gray-500 dark:text-gray-400">${formatFileSize(file.size)}</p>
938
+ </div>
939
+ </div>`;
940
+ filePreview.appendChild(previewItem);
941
+ };
942
+ reader.onerror = () => {
943
+ previewItem.innerHTML = `<p class="text-red-500 dark:text-red-400 text-xs p-2">Erreur lecture image: ${escapeHtml(file.name)}</p>`;
944
+ filePreview.appendChild(previewItem);
945
+ };
946
+ reader.readAsDataURL(file);
947
+ } else {
948
+ previewItem.innerHTML = `
949
+ <div class="flex items-center w-full">
950
+ <div class="w-10 h-10 flex-shrink-0 mr-2 bg-gray-100 dark:bg-gray-800 rounded flex items-center justify-center">
951
+ <i class="fa-solid ${getFileIcon(file.type)} text-gray-500 dark:text-gray-400 text-lg"></i>
952
+ </div>
953
+ <div class="overflow-hidden flex-grow">
954
+ <p class="text-xs font-medium truncate text-gray-800 dark:text-gray-200">${escapeHtml(file.name)}</p>
955
+ <p class="text-xs text-gray-500 dark:text-gray-400">${formatFileSize(file.size)}</p>
956
+ </div>
957
  </div>`;
958
+ filePreview.appendChild(previewItem);
959
+ }
960
+ });
961
+
962
+ // Afficher un message si d'autres fichiers ne sont pas prévisualisés
963
+ if (filesList.length > maxPreviews) {
964
+ const moreInfo = document.createElement('p');
965
+ moreInfo.className = 'text-xs text-gray-500 dark:text-gray-400 text-center mt-1 px-2';
966
+ moreInfo.textContent = `+ ${filesList.length - maxPreviews} autre${filesList.length - maxPreviews > 1 ? 's' : ''} fichier${filesList.length - maxPreviews > 1 ? 's' : ''}`;
967
+ filePreview.appendChild(moreInfo);
 
 
 
 
 
 
 
 
 
968
  }
969
+
970
+ filePreview.classList.remove('hidden');
971
+ previewArea.classList.remove('hidden');
972
  } else {
973
  clearFileInput();
974
  }
975
  });
976
+ // END: Replaced fileUpload event listener
977
+
978
  function getFileIcon(fileType) {
979
  if (!fileType) return 'fa-file';
980
  if (fileType.includes('pdf')) return 'fa-file-pdf';
 
1002
  setTimeout(() => adjustTextareaHeight(promptInput), 0);
1003
  } else if (!isMobile && !e.shiftKey) {
1004
  e.preventDefault();
1005
+ // Modified condition to check filesList
1006
+ if (!sendButton.disabled && (promptInput.value.trim() || filesList.length > 0)) {
1007
  chatForm.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
1008
  }
1009
  } else if (e.shiftKey) {
1010
  setTimeout(() => adjustTextareaHeight(promptInput), 0);
1011
  if (isMobile) {
1012
  e.preventDefault();
1013
+ // Modified condition to check filesList
1014
+ if (!sendButton.disabled && (promptInput.value.trim() || filesList.length > 0)) {
1015
  chatForm.dispatchEvent(new Event('submit', { bubbles: true, cancelable: true }));
1016
  }
1017
  }
 
1025
  });
1026
  adjustTextareaHeight(promptInput);
1027
 
1028
+ // START: Modified chatForm submit listener
1029
  chatForm.addEventListener('submit', async (e) => {
1030
  e.preventDefault();
1031
  const prompt = promptInput.value.trim();
 
1032
  const useWebSearch = webSearchToggle.checked;
1033
  const useAdvanced = advancedToggle.checked;
1034
+
1035
  if (sendButton.disabled) return;
1036
+ // Check against filesList instead of fileUpload.files
1037
+ if (!prompt && filesList.length === 0) {
1038
  promptInput.focus();
1039
  return;
1040
  }
1041
+
1042
  errorMessageDiv.classList.add('hidden');
1043
+
1044
+ // Vérification du cooldown pour le raisonnement avancé
1045
  if (useAdvanced) {
1046
  const now = Date.now();
1047
  if (advancedToggleCooldownEndTime > 0 && now < advancedToggleCooldownEndTime) {
 
1050
  return;
1051
  }
1052
  }
1053
+
1054
+ // Création du message utilisateur avec potentiellement plusieurs fichiers
1055
  let userMessageText = prompt;
1056
+ if (filesList.length > 0) {
1057
+ const fileNames = filesList.map(f => f.name).join(', ');
1058
+ const filesText = filesList.length === 1
1059
+ ? `[Fichier joint: ${escapeHtml(fileNames)}]`
1060
+ : `[${filesList.length} fichiers joints: ${escapeHtml(fileNames)}]`;
1061
+
1062
+ userMessageText = prompt ? `${prompt}\n${filesText}` : filesText;
1063
  }
1064
+
1065
  addMessageToChat('user', userMessageText);
1066
+
1067
+ // Préparation des données à envoyer
1068
  const formData = new FormData();
1069
  formData.append('prompt', prompt);
1070
  formData.append('web_search', useWebSearch);
1071
  formData.append('advanced_reasoning', useAdvanced);
1072
+
1073
+ // Ajout de tous les fichiers au formData avec la clé 'file[]'
1074
+ filesList.forEach(file => {
1075
+ formData.append('file[]', file);
1076
+ });
1077
+
1078
+ // Réinitialisation des champs et gestion des paramètres
1079
  promptInput.value = '';
1080
  adjustTextareaHeight(promptInput);
1081
+ clearFileInput(); // Clears filesList as well now
1082
+
1083
  if (useAdvanced) {
1084
  startAdvancedCooldownTimer();
1085
  advancedToggle.checked = false;
1086
  }
1087
  webSearchToggle.checked = false;
1088
  showLoading(true);
1089
+
1090
+ // Envoi de la requête et gestion de la réponse (aucun changement nécessaire ici)
1091
  try {
1092
  const response = await fetch(API_CHAT_ENDPOINT, { method: 'POST', body: formData });
1093
  const data = await response.json();
1094
  if (!response.ok) {
1095
+ throw new Error(data.error || `Erreur serveur (${response.status}): ${response.statusText}`);
1096
  }
1097
  if (data.success && data.message) {
1098
  addMessageToChat('assistant', data.message, true);
1099
+ } else if (data.error) {
1100
+ throw new Error(data.error);
1101
+ }
1102
+ else {
1103
+ throw new Error("Réponse invalide ou vide du serveur.");
1104
  }
1105
  } catch (error) {
1106
  console.error("Chat Error:", error);
 
1110
  promptInput.focus();
1111
  }
1112
  });
1113
+ // END: Modified chatForm submit listener
1114
 
1115
  // Effacement de la conversation
1116
  clearForm.addEventListener('submit', async (e) => {
 
1145
  clearButton.disabled = true;
1146
  clearButton.innerHTML = '<i class="fa-solid fa-spinner fa-spin mr-1.5"></i><span class="hidden sm:inline">Effacement...</span>';
1147
  try {
1148
+ const response = await fetch(CLEAR_ENDPOINT, {
1149
  method: 'POST',
1150
  headers: {
1151
  'X-Requested-With': 'XMLHttpRequest'
 
1157
  messagesToRemove.forEach(el => el.remove());
1158
  addMessageToChat('assistant', "Conversation effacée. Comment puis-je vous aider maintenant ?", true);
1159
  errorMessageDiv.classList.add('hidden');
1160
+ clearFileInput(); // Also clear any lingering file selections
1161
  } else {
1162
  throw new Error(data.error || "Impossible d'effacer la conversation.");
1163
  }
 
1218
  });
1219
  </script>
1220
  </body>
1221
+ </html>