Spaces:
Running
Running
| document.getElementById('resumerButton').addEventListener('click', loadResumerPage); | |
| document.getElementById('traductionbutton').addEventListener('click', loadTraductionPage); | |
| document.getElementById('qesdocButton').addEventListener('click', loadDocPage); | |
| document.getElementById('visualisationButton').addEventListener('click', loadVisualisationPage); | |
| document.getElementById('interpretationButton').addEventListener('click', loadInterpretationPage); | |
| document.getElementById('qesimgButton').addEventListener('click', loadImagePage); | |
| //quand on clique sur le boutton resumer ------------------------ | |
| function loadResumerPage() { | |
| document.body.style.setProperty('--background-image', "url('resumer2.webp')"); | |
| // Effacer uniquement le contenu de la page sans casser le script | |
| let appContainer = document.createElement("div"); | |
| appContainer.classList.add("app-container"); | |
| appContainer.innerHTML = ` | |
| <div class="sidebar"> | |
| <div class="logo-container"> | |
| <div class="logo-top">SMARTDOC</div> | |
| <div class="logo-bottom">AI</div> | |
| </div> | |
| <a href="principal.html" class="home-link"> | |
| <img src="https://cdn-icons-png.flaticon.com/512/1946/1946436.png" | |
| alt="Accueil" | |
| class="home-icon" | |
| style="filter: brightness(0) saturate(100%) invert(71%) sepia(16%) saturate(4251%) hue-rotate(180deg) brightness(104%) contrast(91%);"> | |
| </a> | |
| <div class="menu-section"> | |
| <button class="menu-btn" id="traductionbutton">TRANSLATE</button> | |
| <button class="menu-btn" id="qesdocButton">DOC-QUESTIONS</button> | |
| <button class="menu-btn" id="visualisationButton">VISUALIZATION</button> | |
| </div> | |
| <div class="menu-section"> | |
| <div class="menu-title">IMAGES</div> | |
| <button class="menu-btn" id="interpretationButton">INTERPRETATION</button> | |
| <button class="menu-btn" id="qesimgButton">IMAGES-QUESTIONS</button> | |
| </div> | |
| </div> | |
| <div class="main-content-area"> | |
| <div class="document-container"> | |
| <h1 class="document-main-title">Documents Operations</h1> | |
| <h2 class="document-subtitle">SUMMARIZE 📋</h2> | |
| <div class="upload-container"> | |
| <div class="file-drop-zone" id="fileDropZone"> | |
| <label for="fileInput" class="file-upload-label"> | |
| <img src="up.png" id="uploadIcon" class="upload-icon" alt="Upload"> | |
| <span class="drop-text" id="dropText">Drop your file here or click to browse</span> | |
| </label> | |
| <input type="file" id="fileInput" class="file-input" accept=".doc,.docx,.xls,.xlsx,.pdf,.ppt,.pptx" hidden> | |
| </div> | |
| <button class="summary-action-btn">SUMMARIZE</button> | |
| </div> | |
| <div class="results-container"> | |
| <div class="results-placeholder"> | |
| <div id="scrollableResult" class="scrollable-text"> | |
| <p id="documentResult" class="placeholder-text" data-summary-text=""> | |
| The result will appear here... | |
| </p> | |
| <!-- Boutons de téléchargement visibles en bas --> | |
| <div id="downloadSection" style="display: none; margin-top: 20px;"> | |
| <h3 style="color: black; margin-bottom: 10px;">Download the summary</h3> | |
| <div style="display: flex; gap: 10px; flex-wrap: wrap; justify-content: center;"> | |
| <button id="downloadPdf" class="download-btn">PDF</button> | |
| <button id="downloadWord" class="download-btn">Word</button> | |
| <button id="downloadPpt" class="download-btn">PowerPoint</button> | |
| <button id="downloadTxt" class="download-btn">Text</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| // Insérer la nouvelle interface sans écraser les scripts | |
| document.body.innerHTML = ""; | |
| document.body.appendChild(appContainer); | |
| // Ajouter l'événement de clic pour le bouton "RÉSUMER" | |
| document.querySelector('.summary-action-btn').addEventListener('click', async () => { | |
| await uploadDocument(); | |
| }); | |
| async function uploadDocument() { | |
| let fileInput = document.getElementById("fileInput"); | |
| let resultElement = document.getElementById("documentResult"); | |
| if (fileInput.files.length === 0) { | |
| resultElement.innerText = "⚠️ No file selected !"; | |
| return; | |
| } | |
| resultElement.innerText = "Loading the summary... 🕐"; | |
| let formData = new FormData(); | |
| formData.append("file", fileInput.files[0]); | |
| try { | |
| let response = await fetch("https://aiwebdev-smartdocai.hf.space/summarize/", { | |
| method: "POST", | |
| body: formData, | |
| headers: { "Accept": "application/json" } | |
| }); | |
| if (!response.ok) { | |
| throw new Error("Erreur de requête !"); | |
| } | |
| let data = await response.json(); | |
| console.log("📤 Réponse du serveur :", data); | |
| if (data.message && data.message.includes("Modèle en cours de chargement")) { | |
| resultElement.innerText = "Le résumé est en cours de génération. Veuillez patienter... 🕐"; | |
| return; | |
| } | |
| if (data.summary) { | |
| resultElement.innerHTML = ` | |
| <div style="display: flex; align-items: center; justify-content: flex-end; margin-bottom: 10px;"> | |
| <button id="playVoiceBtn" style=" | |
| background: linear-gradient(125deg, rgba(163, 94, 237, 0.9) 0%, rgba(65, 159, 232, 0.9) 75%); | |
| color: white; | |
| border: none; | |
| padding: 10px 16px; | |
| border-radius: 12px; | |
| cursor: pointer; | |
| font-size: 14px; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.1); | |
| transition: transform 0.2s; | |
| "> | |
| 🔊 Listen to Summary | |
| </button> | |
| </div> | |
| <h3 class="centered-title">📝 Summary generated :</h3> | |
| <br> | |
| <p id="summaryText">${data.summary}</p> | |
| `; | |
| document.getElementById("documentResult").dataset.summaryText = data.summary; | |
| document.getElementById("downloadSection").style.display = "block"; | |
| const playVoiceBtn = document.getElementById("playVoiceBtn"); | |
| let isSpeaking = false; | |
| let utterance = null; | |
| playVoiceBtn.addEventListener("click", function () { | |
| if (isSpeaking) { | |
| // Si la lecture est en cours, on l'arrête | |
| window.speechSynthesis.cancel(); | |
| isSpeaking = false; | |
| } else { | |
| // Sinon, on commence à lire | |
| const textToRead = document.getElementById("summaryText").textContent; | |
| utterance = new SpeechSynthesisUtterance(textToRead); | |
| utterance.lang = "en-US"; // ou "fr-FR" | |
| utterance.onend = function () { | |
| // Lecture terminée | |
| isSpeaking = false; | |
| }; | |
| window.speechSynthesis.speak(utterance); | |
| isSpeaking = true; | |
| } | |
| }); | |
| } | |
| else { | |
| resultElement.innerText = "❌ Summary not available."; | |
| } | |
| } catch (error) { | |
| console.error("❌ Erreur : ", error); | |
| resultElement.innerText = "Erreur lors de la demande !"; | |
| } | |
| } | |
| document.addEventListener("click", (e) => { | |
| const text = document.getElementById("documentResult").dataset.summaryText; | |
| if (!text) return; | |
| if (e.target.id === "downloadPdf") { | |
| const { jsPDF } = window.jspdf; | |
| const doc = new jsPDF(); | |
| let lines = doc.splitTextToSize(text, 180); | |
| doc.text(lines, 10, 10); | |
| doc.save('resume.pdf'); | |
| } | |
| if (e.target.id === "downloadWord") { | |
| const { Document, Paragraph, TextRun, Packer } = window.docx; | |
| const doc = new Document({ | |
| sections: [{ | |
| children: [new Paragraph({ children: [new TextRun(text)] })] | |
| }] | |
| }); | |
| Packer.toBlob(doc).then(blob => { | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = 'resume.docx'; | |
| a.click(); | |
| URL.revokeObjectURL(url); | |
| }); | |
| } | |
| if (e.target.id === "downloadPpt") { | |
| const pptx = new window.PptxGenJS(); | |
| const slide = pptx.addSlide(); | |
| slide.addText(text, { x: 1, y: 1, w: 8, h: 4 }); | |
| pptx.writeFile({ fileName: 'resume.pptx' }); | |
| } | |
| if (e.target.id === "downloadTxt") { | |
| const blob = new Blob([text], { type: 'text/plain' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = 'resume.txt'; | |
| a.click(); | |
| URL.revokeObjectURL(url); | |
| } | |
| }); | |
| // Reconnexion des boutons du menu latéral | |
| document.getElementById('traductionbutton').addEventListener('click', loadTraductionPage); | |
| document.getElementById('qesdocButton').addEventListener('click', loadDocPage); | |
| document.getElementById('visualisationButton').addEventListener('click', loadVisualisationPage); | |
| document.getElementById('interpretationButton').addEventListener('click', loadInterpretationPage); | |
| document.getElementById('qesimgButton').addEventListener('click', loadImagePage); | |
| // Gestion du dropzone | |
| const fileInput = document.getElementById('fileInput'); | |
| const dropText = document.getElementById('dropText'); | |
| const uploadIcon = document.getElementById('uploadIcon'); | |
| dropText.addEventListener('click', function(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| fileInput.click(); | |
| }); | |
| uploadIcon.addEventListener('click', function(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', function(event) { | |
| let file = event.target.files[0]; | |
| if (file) { | |
| dropText.textContent = file.name; | |
| uploadIcon.style.display = "none"; | |
| } | |
| }); | |
| } | |
| //Quand on clique sur le boutton traduction --------------- | |
| function loadTraductionPage() { | |
| document.body.style.setProperty('--background-image', "url('traduction.webp')"); | |
| let appContainer = document.createElement("div"); | |
| appContainer.classList.add("app-container"); | |
| appContainer.innerHTML = ` | |
| <div class="sidebar"> | |
| <div class="logo-container"> | |
| <div class="logo-top">SMARTDOCS</div> | |
| <div class="logo-bottom">AI</div> | |
| </div> | |
| <a href="principal.html" class="home-link"> | |
| <img src="https://cdn-icons-png.flaticon.com/512/1946/1946436.png" | |
| alt="Accueil" | |
| class="home-icon" | |
| style="filter: brightness(0) saturate(100%) invert(71%) sepia(16%) saturate(4251%) hue-rotate(180deg) brightness(104%) contrast(91%);"> | |
| </a> | |
| <div class="menu-section"> | |
| <button class="menu-btn" id="resumerButton">SUMMARIZE</button> | |
| <button class="menu-btn" id="qesdocButton">DOC-QUESTIONS</button> | |
| <button class="menu-btn" id="visualisationButton">VISUALIZATION</button> | |
| </div> | |
| <div class="menu-section"> | |
| <div class="menu-title">IMAGES</div> | |
| <button class="menu-btn" id="interpretationButton">INTERPRETATION</button> | |
| <button class="menu-btn" id="qesimgButton">IMAGES-QUESTIONS</button> | |
| </div> | |
| </div> | |
| <div class="main-content-area"> | |
| <div class="document-container"> | |
| <h1 class="document-main-title">Documents Operations</h1> | |
| <h2 class="document-subtitle">TRANSLATE 🌍 </h2> | |
| <div class="upload-container"> | |
| <div class="file-drop-zone" id="fileDropZone"> | |
| <label for="translateFile" class="file-upload-label"> | |
| <img src="up.png" id="uploadIcon" class="upload-icon" alt="Upload"> | |
| <span class="drop-text" id="dropText">Drop your file here or click to browse</span> | |
| </label> | |
| <input type="file" id="translateFile" class="file-input" accept=".doc,.docx,.xls,.xlsx,.pdf,.ppt,.pptx" hidden> | |
| </div> | |
| <div class="action-container"> | |
| <select id="targetLanguageSelect" class="language-dropdown"> | |
| <option value="">Select language</option> | |
| <option value="af">Afrikaans</option> | |
| <option value="am">Amharic</option> | |
| <option value="ar">Arabic</option> | |
| <option value="ast">Asturian</option> | |
| <option value="az">Azerbaijani</option> | |
| <option value="ba">Bashkir</option> | |
| <option value="be">Belarusian</option> | |
| <option value="bg">Bulgarian</option> | |
| <option value="bn">Bengali</option> | |
| <option value="br">Breton</option> | |
| <option value="bs">Bosnian</option> | |
| <option value="ca">Catalan; Valencian</option> | |
| <option value="ceb">Cebuano</option> | |
| <option value="cs">Czech</option> | |
| <option value="cy">Welsh</option> | |
| <option value="da">Danish</option> | |
| <option value="de">German</option> | |
| <option value="el">Greek</option> | |
| <option value="en">English</option> | |
| <option value="es">Spanish</option> | |
| <option value="et">Estonian</option> | |
| <option value="fa">Persian</option> | |
| <option value="ff">Fulah</option> | |
| <option value="fi">Finnish</option> | |
| <option value="fr">French</option> | |
| <option value="fy">Western Frisian</option> | |
| <option value="ga">Irish</option> | |
| <option value="gd">Gaelic; Scottish Gaelic</option> | |
| <option value="gl">Galician</option> | |
| <option value="gu">Gujarati</option> | |
| <option value="ha">Hausa</option> | |
| <option value="he">Hebrew</option> | |
| <option value="hi">Hindi</option> | |
| <option value="hr">Croatian</option> | |
| <option value="ht">Haitian; Haitian Creole</option> | |
| <option value="hu">Hungarian</option> | |
| <option value="hy">Armenian</option> | |
| <option value="id">Indonesian</option> | |
| <option value="ig">Igbo</option> | |
| <option value="ilo">Iloko</option> | |
| <option value="is">Icelandic</option> | |
| <option value="it">Italian</option> | |
| <option value="ja">Japanese</option> | |
| <option value="jv">Javanese</option> | |
| <option value="ka">Georgian</option> | |
| <option value="kk">Kazakh</option> | |
| <option value="km">Central Khmer</option> | |
| <option value="kn">Kannada</option> | |
| <option value="ko">Korean</option> | |
| <option value="lb">Luxembourgish</option> | |
| <option value="lg">Ganda</option> | |
| <option value="ln">Lingala</option> | |
| <option value="lo">Lao</option> | |
| <option value="lt">Lithuanian</option> | |
| <option value="lv">Latvian</option> | |
| <option value="mg">Malagasy</option> | |
| <option value="mk">Macedonian</option> | |
| <option value="ml">Malayalam</option> | |
| <option value="mn">Mongolian</option> | |
| <option value="mr">Marathi</option> | |
| <option value="ms">Malay</option> | |
| <option value="my">Burmese</option> | |
| <option value="ne">Nepali</option> | |
| <option value="nl">Dutch; Flemish</option> | |
| <option value="no">Norwegian</option> | |
| <option value="ns">Northern Sotho</option> | |
| <option value="oc">Occitan (post 1500)</option> | |
| <option value="or">Oriya</option> | |
| <option value="pa">Panjabi; Punjabi</option> | |
| <option value="pl">Polish</option> | |
| <option value="ps">Pushto; Pashto</option> | |
| <option value="pt">Portuguese</option> | |
| <option value="ro">Romanian; Moldavian</option> | |
| <option value="ru">Russian</option> | |
| <option value="sd">Sindhi</option> | |
| <option value="si">Sinhala; Sinhalese</option> | |
| <option value="sk">Slovak</option> | |
| <option value="sl">Slovenian</option> | |
| <option value="so">Somali</option> | |
| <option value="sq">Albanian</option> | |
| <option value="sr">Serbian</option> | |
| <option value="ss">Swati</option> | |
| <option value="su">Sundanese</option> | |
| <option value="sv">Swedish</option> | |
| <option value="sw">Swahili</option> | |
| <option value="ta">Tamil</option> | |
| <option value="th">Thai</option> | |
| <option value="tl">Tagalog</option> | |
| <option value="tn">Tswana</option> | |
| <option value="tr">Turkish</option> | |
| <option value="uk">Ukrainian</option> | |
| <option value="ur">Urdu</option> | |
| <option value="uz">Uzbek</option> | |
| <option value="vi">Vietnamese</option> | |
| <option value="wo">Wolof</option> | |
| <option value="xh">Xhosa</option> | |
| <option value="yi">Yiddish</option> | |
| <option value="yo">Yoruba</option> | |
| <option value="zh">Chinese</option> | |
| <option value="zu">Zulu</option> | |
| </select> | |
| <button class="translate" id="translateButton">Translate</button> | |
| </div> | |
| </div> | |
| <div class="results-container"> | |
| <div class="results-placeholder"> | |
| <div id="scrollableResult" class="scrollable-text"> | |
| <p class="placeholder-text" id="translateResult">The result will appear here...</p> | |
| <div id="downloadSection" style="display: none; margin-top: 20px;"> | |
| <h3 style="color: white; margin-bottom: 10px;">Download the translation</h3> | |
| <div style="display: flex; gap: 10px;"> | |
| <button id="downloadPdf" class="download-btn">PDF</button> | |
| <button id="downloadWord" class="download-btn">Word</button> | |
| <button id="downloadPpt" class="download-btn">PowerPoint</button> | |
| <button id="downloadTxt" class="download-btn">Texte</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| document.body.innerHTML = ""; | |
| document.body.appendChild(appContainer); | |
| // Chargement des librairies externes | |
| loadExternalLibs(); | |
| // Gestion des événements | |
| setupEventListeners(); | |
| function loadExternalLibs() { | |
| if (!window.jspdf) { | |
| const script = document.createElement('script'); | |
| script.src = 'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js'; | |
| document.head.appendChild(script); | |
| } | |
| if (!window.docx) { | |
| const script = document.createElement('script'); | |
| script.src = 'https://cdnjs.cloudflare.com/ajax/libs/docx/7.8.2/docx.min.js'; | |
| document.head.appendChild(script); | |
| } | |
| if (!window.PptxGenJS) { | |
| const script = document.createElement('script'); | |
| script.src = 'https://cdnjs.cloudflare.com/ajax/libs/PptxGenJS/3.11.0/pptxgen.min.js'; | |
| document.head.appendChild(script); | |
| } | |
| } | |
| function setupEventListeners() { | |
| // Navigation | |
| document.getElementById('resumerButton').addEventListener('click', loadResumerPage); | |
| document.getElementById('qesdocButton').addEventListener('click', loadDocPage); | |
| document.getElementById('visualisationButton').addEventListener('click', loadVisualisationPage); | |
| document.getElementById('interpretationButton').addEventListener('click', loadInterpretationPage); | |
| document.getElementById('qesimgButton').addEventListener('click', loadImagePage); | |
| // Gestion des fichiers | |
| const fileInput = document.getElementById('translateFile'); | |
| const dropText = document.getElementById('dropText'); | |
| const uploadIcon = document.getElementById('uploadIcon'); | |
| dropText.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| fileInput.click(); | |
| }); | |
| uploadIcon.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', (e) => { | |
| if (e.target.files[0]) { | |
| dropText.textContent = e.target.files[0].name; | |
| uploadIcon.style.display = "none"; | |
| } | |
| }); | |
| // Traduction | |
| document.getElementById('translateButton').addEventListener('click', uploadForTranslation); | |
| // Téléchargements | |
| document.getElementById('downloadPdf').addEventListener('click', downloadAsPdf); | |
| document.getElementById('downloadWord').addEventListener('click', downloadAsWord); | |
| document.getElementById('downloadPpt').addEventListener('click', downloadAsPowerPoint); | |
| document.getElementById('downloadTxt').addEventListener('click', downloadAsText); | |
| } | |
| async function uploadForTranslation() { | |
| const fileInput = document.getElementById("translateFile"); | |
| const targetLang = document.getElementById("targetLanguageSelect").value; | |
| const resultElement = document.getElementById("translateResult"); | |
| if (!fileInput.files[0]) { | |
| resultElement.innerText = "No file selected"; | |
| return; | |
| } | |
| if (!targetLang) { | |
| resultElement.innerText = "Please select a language"; | |
| return; | |
| } | |
| const formData = new FormData(); | |
| formData.append("file", fileInput.files[0]); | |
| formData.append("target_lang", targetLang); | |
| try { | |
| resultElement.innerText = "Translation in progress...🕐"; | |
| const response = await fetch("https://aiwebdev-smartdocai.hf.space/translate/", { | |
| method: "POST", | |
| body: formData, | |
| headers: { "Accept": "application/json" } | |
| }); | |
| if (!response.ok) { | |
| throw new Error("Erreur de requête: " + await response.text()); | |
| } | |
| const data = await response.json(); | |
| if (data.translated_text) { | |
| resultElement.innerText = "📝 Translate :\n " + data.translated_text; | |
| // Stocker le texte traduit pour le téléchargement | |
| resultElement.dataset.translatedText = data.translated_text; | |
| // Afficher les options de téléchargement | |
| document.getElementById("downloadSection").style.display = "block"; | |
| } else { | |
| resultElement.innerText = "❌ Translation not available."; | |
| } | |
| } catch (error) { | |
| console.error("Erreur:", error); | |
| resultElement.innerText = "Échec de la traduction: " + error.message; | |
| } | |
| } | |
| function downloadAsPdf() { | |
| const text = document.getElementById("translateResult").dataset.translatedText; | |
| if (!text) return; | |
| const { jsPDF } = window.jspdf; | |
| const doc = new jsPDF(); | |
| doc.text(text, 10, 10); | |
| doc.save('traduction.pdf'); | |
| } | |
| async function downloadAsWord() { | |
| const text = document.getElementById("translateResult").dataset.translatedText; | |
| if (!text) return; | |
| const { Document, Paragraph, TextRun, Packer } = window.docx; | |
| const doc = new Document({ | |
| sections: [{ | |
| properties: {}, | |
| children: [ | |
| new Paragraph({ | |
| children: [ | |
| new TextRun(text) | |
| ] | |
| }) | |
| ] | |
| }] | |
| }); | |
| Packer.toBlob(doc).then(blob => { | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = 'traduction.docx'; | |
| a.click(); | |
| URL.revokeObjectURL(url); | |
| }); | |
| } | |
| function downloadAsPowerPoint() { | |
| const text = document.getElementById("translateResult").dataset.translatedText; | |
| if (!text) return; | |
| const pptx = new window.PptxGenJS(); | |
| const slide = pptx.addSlide(); | |
| slide.addText(text, { x: 1, y: 1, w: 8, h: 4 }); | |
| pptx.writeFile({ fileName: 'traduction.pptx' }); | |
| } | |
| function downloadAsText() { | |
| const text = document.getElementById("translateResult").dataset.translatedText; | |
| if (!text) return; | |
| const blob = new Blob([text], { type: 'text/plain' }); | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = 'traduction.txt'; | |
| a.click(); | |
| URL.revokeObjectURL(url); | |
| } | |
| } | |
| function loadDocPage() { | |
| document.body.style.setProperty('--background-image', "url('qstdoc2.webp')"); | |
| // Créer une nouvelle structure pour ne pas écraser les événements | |
| let appContainer = document.createElement("div"); | |
| appContainer.classList.add("app-container"); | |
| appContainer.innerHTML = ` | |
| <div class="sidebar"> | |
| <div class="logo-container"> | |
| <div class="logo-top">SMARTDOCS</div> | |
| <div class="logo-bottom">AI</div> | |
| </div> | |
| <a href="principal.html" class="home-link"> | |
| <img src="https://cdn-icons-png.flaticon.com/512/1946/1946436.png" | |
| alt="Accueil" | |
| class="home-icon" | |
| style="filter: brightness(0) saturate(100%) invert(71%) sepia(16%) saturate(4251%) hue-rotate(180deg) brightness(104%) contrast(91%);"> | |
| </a> | |
| <div class="menu-section"> | |
| <button class="menu-btn" id="resumerButton">SUMMARIZE</button> | |
| <button class="menu-btn" id="traductionbutton">TRANSLATE</button> | |
| <button class="menu-btn" id="visualisationButton">VISUALIZATION</button> | |
| </div> | |
| <div class="menu-section"> | |
| <div class="menu-title">IMAGES</div> | |
| <button class="menu-btn" id="interpretationButton">INTERPRETATION</button> | |
| <button class="menu-btn" id="qesimgButton">IMAGES-QUESTIONS</button> | |
| </div> | |
| </div> | |
| <div class="main-content-area"> | |
| <div class="document-container"> | |
| <h1 class="document-main-title">Documents Operations</h1> | |
| <h2 class="document-subtitle">DOCUMENTS QUESTIONS 📄❓</h2> | |
| <div class="upload-container"> | |
| <div class="file-drop-zone" id="fileDropZone"> | |
| <label for="fileInput" class="file-upload-label"> | |
| <img src="up.png" id="uploadIcon" class="upload-icon" alt="Upload"> | |
| <span class="drop-text" id="dropText">Drop your file here or click to browse</span> | |
| </label> | |
| <input type="file" id="fileInput" class="file-input" accept=".doc,.docx,.xls,.xlsx,.pdf,.ppt,.pptx" hidden> | |
| </div> | |
| <div class="question-container"> | |
| <div class="question"> | |
| <input type="text" id="questionInput" placeholder="Enter your question here..."> | |
| </div> | |
| <button class="question-btn" id="askDocBtn">Send</button> | |
| </div> | |
| </div> | |
| <div class="results-container"> | |
| <div class="results-placeholder"> | |
| <p id="documentAnswer" class="placeholder-text">The result will appear here...</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| // Insérer la nouvelle structure sans écraser les événements | |
| document.body.innerHTML = ""; | |
| document.body.appendChild(appContainer); | |
| // Réassocier les événements aux boutons | |
| document.getElementById('resumerButton').addEventListener('click', loadResumerPage); | |
| document.getElementById('traductionbutton').addEventListener('click', loadTraductionPage); | |
| document.getElementById('visualisationButton').addEventListener('click', loadVisualisationPage); | |
| document.getElementById('interpretationButton').addEventListener('click', loadInterpretationPage); | |
| document.getElementById('qesimgButton').addEventListener('click', loadImagePage); | |
| const fileInput = document.getElementById('fileInput'); | |
| const dropText = document.getElementById('dropText'); | |
| const uploadIcon = document.getElementById('uploadIcon'); | |
| + | |
| dropText.addEventListener('click', function(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| fileInput.click(); | |
| }); | |
| uploadIcon.addEventListener('click', function(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', function(event) { | |
| let file = event.target.files[0]; | |
| if (file) { | |
| dropText.textContent = file.name; | |
| uploadIcon.style.display = "none"; | |
| } | |
| }); | |
| const askBtn = document.getElementById('askDocBtn'); | |
| askBtn.addEventListener('click', async () => { | |
| const file = fileInput.files[0]; | |
| const question = document.getElementById('questionInput').value; | |
| const answerDiv = document.getElementById('documentAnswer'); | |
| if (!file || !question) { | |
| answerDiv.innerHTML = "⚠️ No question or file selected."; | |
| return; | |
| } | |
| const formData = new FormData(); | |
| formData.append("file", file); | |
| formData.append("question", question); | |
| answerDiv.innerHTML = "⏳Document analysis in progress..."; | |
| try { | |
| const response = await fetch("/doc-qa/", { | |
| method: "POST", | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (data.answer) { | |
| answerDiv.innerHTML = ` | |
| <div style="display: flex; align-items: center; justify-content: flex-end; margin-bottom: 10px;"> | |
| <button id="playAnswerVoiceBtn" style=" | |
| background: linear-gradient(125deg, rgba(163, 94, 237, 0.9) 0%, rgba(65, 159, 232, 0.9) 75%); | |
| color: white; | |
| border: none; | |
| padding: 10px 16px; | |
| border-radius: 12px; | |
| cursor: pointer; | |
| font-size: 14px; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.1); | |
| transition: transform 0.2s; | |
| "> | |
| 🔊 Listen to Answer | |
| </button> | |
| </div> | |
| <h3 class="centered-title">✅ The result :</h3> | |
| <br> | |
| <p id="answerText">${data.answer}</p> | |
| `; | |
| const playVoiceBtn = document.getElementById("playAnswerVoiceBtn"); | |
| playVoiceBtn.addEventListener("click", function () { | |
| const textToRead = document.getElementById("answerText").textContent; | |
| const utterance = new SpeechSynthesisUtterance(textToRead); | |
| utterance.lang = "en-US"; // ou adapte ici si tu as des réponses en français | |
| window.speechSynthesis.speak(utterance); | |
| }); | |
| } else { | |
| answerDiv.innerHTML = `❌ ${data.error || "Erreur inconnue"}`; | |
| } | |
| } catch (error) { | |
| answerDiv.innerHTML = "❌ Erreur lors de l'envoi de la requête."; | |
| } | |
| }); | |
| } | |
| //quand on clique sur visualisation ---------------------- | |
| function loadVisualisationPage() { | |
| document.body.style.setProperty('--background-image', "url('visualisation.webp')"); | |
| const appContainer = document.createElement("div"); | |
| appContainer.className = "app-container"; | |
| appContainer.innerHTML = ` | |
| <div class="sidebar"> | |
| <div class="logo-container"> | |
| <div class="logo-top">SMARTDOCS</div> | |
| <div class="logo-bottom">AI</div> | |
| </div> | |
| <a href="principal.html" class="home-link"> | |
| <img src="https://cdn-icons-png.flaticon.com/512/1946/1946436.png" | |
| alt="Accueil" | |
| class="home-icon" | |
| style="filter: brightness(0) saturate(100%) invert(71%) sepia(16%) saturate(4251%) hue-rotate(180deg) brightness(104%) contrast(91%);"> | |
| </a> | |
| <div class="menu-section"> | |
| <button class="menu-btn" id="resumerButton">SUMMARIZE</button> | |
| <button class="menu-btn" id="traductionbutton">TRANSLATE</button> | |
| <button class="menu-btn" id="qesdocButton">DOC-QUESTIONS</button> | |
| </div> | |
| <div class="menu-section"> | |
| <div class="menu-title">IMAGES</div> | |
| <button class="menu-btn" id="interpretationButton">INTERPRETATION</button> | |
| <button class="menu-btn" id="qesimgButton">IMAGES-QUESTIONS</button> | |
| </div> | |
| </div> | |
| <div class="main-content-area"> | |
| <div class="document-container"> | |
| <h1 class="document-main-title">Documents Operations</h1> | |
| <h2 class="document-subtitle">VISUALIZATION 📊</h2> | |
| <div class="upload-container"> | |
| <div class="file-drop-zone" id="fileDropZone"> | |
| <label for="graphFileInput" class="file-upload-label"> | |
| <img src="up.png" id="uploadIcon" class="upload-icon" alt="Upload"> | |
| <span class="drop-text" id="dropText">Drop your file here or click to browse</span> | |
| </label> | |
| <input type="file" id="graphFileInput" class="file-input" | |
| accept=".doc,.docx,.xls,.xlsx,.pdf,.ppt,.pptx" hidden> | |
| </div> | |
| <div class="graph-action-container"> | |
| <select id="graphTypeSelect" class="language-dropdown"> | |
| <option value="">Select type</option> | |
| <option value="histplot">Histogram</option> | |
| <option value="scatterplot">Point cloud</option> | |
| <option value="lineplot">Curve</option> | |
| <option value="barplot">Bar chart</option> | |
| <option value="boxplot">Boxplot</option> | |
| </select> | |
| <button type="button" id="generateGraphBtn" class="graph-generate-btn">Generate</button> | |
| </div> | |
| </div> | |
| <div class="graph-results-container"> | |
| <div class="graph-results-placeholder"> | |
| <img id="graphResultImage" class="graph-result-img"> | |
| <p class="placeholder-text" id="graphPlaceholderText">The result will appear here...</p> | |
| </div> | |
| <div id="downloadSection" style="display: none; margin-top: 20px; text-align: center;"> | |
| <h3 style="color: white; margin-bottom: 10px;">Download the graph</h3> | |
| <div style="display: flex; justify-content: center; gap: 10px;"> | |
| <button id="downloadPng" class="download-btn">PNG</button> | |
| <button id="downloadJpg" class="download-btn">JPG</button> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| // 3. Nettoyage et insertion | |
| document.body.innerHTML = ""; | |
| document.body.appendChild(appContainer); | |
| // 4. Gestion des événements | |
| const setupEventListeners = () => { | |
| // Navigation | |
| document.getElementById('resumerButton').addEventListener('click', loadResumerPage); | |
| document.getElementById('traductionbutton').addEventListener('click', loadTraductionPage); | |
| document.getElementById('qesdocButton').addEventListener('click', loadDocPage); | |
| document.getElementById('interpretationButton').addEventListener('click', loadInterpretationPage); | |
| document.getElementById('qesimgButton').addEventListener('click', loadImagePage); | |
| // Gestion des fichiers | |
| const fileInput = document.getElementById('graphFileInput'); | |
| const dropText = document.getElementById('dropText'); | |
| const uploadIcon = document.getElementById('uploadIcon'); | |
| dropText.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| fileInput.click(); | |
| }); | |
| uploadIcon.addEventListener('click', (e) => { | |
| e.preventDefault(); | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', (e) => { | |
| if (e.target.files[0]) { | |
| dropText.textContent = e.target.files[0].name; | |
| uploadIcon.style.display = "none"; | |
| // Réinitialiser l'affichage quand un nouveau fichier est sélectionné | |
| document.getElementById("downloadSection").style.display = "none"; | |
| document.getElementById("graphResultImage").style.display = "none"; | |
| document.getElementById("graphPlaceholderText").textContent = "Ready to generate the chart"; | |
| } | |
| }); | |
| // Génération du graphique | |
| document.getElementById('generateGraphBtn').addEventListener('click', generateGraph); | |
| // Téléchargement du graphique | |
| document.getElementById('downloadPng').addEventListener('click', () => downloadGraph('png')); | |
| document.getElementById('downloadJpg').addEventListener('click', () => downloadGraph('jpg')); | |
| }; | |
| // 5. Fonction de génération du graphique | |
| const generateGraph = async () => { | |
| const fileInput = document.getElementById('graphFileInput'); | |
| const graphTypeSelect = document.getElementById('graphTypeSelect'); | |
| const resultImage = document.getElementById('graphResultImage'); | |
| const placeholderText = document.getElementById('graphPlaceholderText'); | |
| const downloadSection = document.getElementById("downloadSection"); | |
| // Validation | |
| if (!fileInput.files[0]) { | |
| placeholderText.textContent = "⚠️No file selected"; | |
| downloadSection.style.display = "none"; | |
| return; | |
| } | |
| if (!graphTypeSelect.value) { | |
| placeholderText.textContent = "⚠️No a chart type selected"; | |
| downloadSection.style.display = "none"; | |
| return; | |
| } | |
| // Préparation de l'interface | |
| resultImage.style.display = "none"; | |
| downloadSection.style.display = "none"; | |
| placeholderText.textContent = "⏳ Graph generation in progress..."; | |
| try { | |
| // Envoi des données | |
| const formData = new FormData(); | |
| formData.append("file", fileInput.files[0]); | |
| formData.append("query", graphTypeSelect.value); | |
| const response = await fetch("/generate_viz/", { | |
| method: "POST", | |
| body: formData, | |
| headers: { 'Accept': 'application/json' } | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`Erreur ${response.status}: ${await response.text()}`); | |
| } | |
| const result = await response.json(); | |
| if (result.error) { | |
| throw new Error(result.error); | |
| } | |
| // Créer une URL de l'image à partir de la chaîne base64 | |
| const imageUrl = `data:image/png;base64,${result.image_base64}`; | |
| // Afficher l'image | |
| resultImage.onload = () => { | |
| // Afficher les options de téléchargement une fois l'image chargée | |
| document.getElementById("downloadSection").style.display = "block"; | |
| placeholderText.textContent = ""; | |
| }; | |
| resultImage.src = imageUrl; | |
| resultImage.style.display = "block"; | |
| } catch (error) { | |
| console.error("Erreur:", error); | |
| placeholderText.textContent = `Erreur: ${error.message}`; | |
| resultImage.style.display = "none"; | |
| downloadSection.style.display = "none"; | |
| } | |
| }; | |
| // 6. Fonction de téléchargement du graphique | |
| const downloadGraph = (format) => { | |
| const resultImage = document.getElementById('graphResultImage'); | |
| if (!resultImage.src || resultImage.style.display === "none") { | |
| alert("Please generate a shart first"); | |
| return; | |
| } | |
| // Créer un canvas pour la conversion | |
| const canvas = document.createElement('canvas'); | |
| const ctx = canvas.getContext('2d'); | |
| canvas.width = resultImage.naturalWidth; | |
| canvas.height = resultImage.naturalHeight; | |
| ctx.drawImage(resultImage, 0, 0); | |
| let mimeType, extension; | |
| switch(format) { | |
| case 'jpg': | |
| mimeType = 'image/jpeg'; | |
| extension = 'jpg'; | |
| break; | |
| default: // PNG par défaut | |
| mimeType = 'image/png'; | |
| extension = 'png'; | |
| } | |
| // Conversion et téléchargement | |
| canvas.toBlob((blob) => { | |
| downloadFile(blob, `graphique.${extension}`); | |
| }, mimeType, format === 'jpg' ? 0.92 : 1); // Qualité à 92% pour JPG, 100% pour PNG | |
| }; | |
| // 7. Fonction utilitaire pour le téléchargement | |
| const downloadFile = (blob, filename) => { | |
| const url = URL.createObjectURL(blob); | |
| const a = document.createElement('a'); | |
| a.href = url; | |
| a.download = filename; | |
| document.body.appendChild(a); | |
| a.click(); | |
| document.body.removeChild(a); | |
| setTimeout(() => URL.revokeObjectURL(url), 100); | |
| }; | |
| // Initialisation | |
| setupEventListeners(); | |
| } | |
| //quand on clique sur interpretation --------------------- | |
| function loadInterpretationPage() { | |
| document.body.style.setProperty('--background-image', "url('interpreter.webp')"); | |
| // Créer une nouvelle structure pour ne pas écraser les événements | |
| let appContainer = document.createElement("div"); | |
| appContainer.classList.add("app-container"); | |
| appContainer.innerHTML = ` | |
| <div class="sidebar"> | |
| <div class="logo-container"> | |
| <div class="logo-top">SMARTDOCS</div> | |
| <div class="logo-bottom">AI</div> | |
| </div> | |
| <a href="principal.html" class="home-link"> | |
| <img src="https://cdn-icons-png.flaticon.com/512/1946/1946436.png" | |
| alt="Accueil" | |
| class="home-icon" | |
| style="filter: brightness(0) saturate(100%) invert(71%) sepia(16%) saturate(4251%) hue-rotate(180deg) brightness(104%) contrast(91%);"> | |
| </a> | |
| <div class="menu-section"> | |
| <button class="menu-btn" id="qesimgButton">IMAGES-QUESTIONS</button> | |
| </div> | |
| <div class="menu-section"> | |
| <div class="menu-title">DOCUMENTS</div> | |
| <button class="menu-btn" id="resumerButton">SUMMARIZE</button> | |
| <button class="menu-btn" id="traductionbutton">TRANSLATE</button> | |
| <button class="menu-btn" id="qesdocButton">DOC-QUESTIONS</button> | |
| <button class="menu-btn" id="visualisationButton">VISUALIZATION</button> | |
| </div> | |
| </div> | |
| <div class="main-content-area"> | |
| <div class="document-container"> | |
| <h1 class="document-main-title">Images Operations</h1> | |
| <h2 class="document-subtitle">IMAGES INTERPRETATION 🏞️🤖</h2> | |
| <div class="upload-container"> | |
| <div class="file-drop-zone" id="fileDropZone"> | |
| <label for="fileInput" class="file-upload-label"> | |
| <img src="up.png" id="uploadIcon" class="upload-icon" alt="Upload"> | |
| <span class="drop-text" id="dropText">Drop your image here or click to browse</span> | |
| </label> | |
| <input type="file" id="fileInput" class="file-input" accept=".jpg,.jpeg,.png,.gif,.bmp,.webp" hidden> | |
| </div> | |
| <button class="summary-action-btn" id="interpretButton">INTERPRET</button> | |
| </div> | |
| <div class="results-container"> | |
| <div class="results-placeholder" id="imageCaptionResult"> | |
| <p class="placeholder-text">The result will appear here...</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| // Insérer la nouvelle structure sans écraser les événements | |
| document.body.innerHTML = ""; | |
| document.body.appendChild(appContainer); | |
| // Réassocier les événements aux boutons | |
| document.getElementById('resumerButton').addEventListener('click', loadResumerPage); | |
| document.getElementById('traductionbutton').addEventListener('click', loadTraductionPage); | |
| document.getElementById('qesdocButton').addEventListener('click', loadDocPage); | |
| document.getElementById('visualisationButton').addEventListener('click', loadVisualisationPage); | |
| document.getElementById('qesimgButton').addEventListener('click', loadImagePage); | |
| const interpretButton = document.getElementById('interpretButton'); | |
| const resultContainer = document.getElementById('imageCaptionResult'); | |
| const fileInput = document.getElementById('fileInput'); | |
| const dropText = document.getElementById('dropText'); | |
| const uploadIcon = document.getElementById('uploadIcon'); | |
| + | |
| dropText.addEventListener('click', function(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| fileInput.click(); | |
| }); | |
| uploadIcon.addEventListener('click', function(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', function(event) { | |
| let file = event.target.files[0]; | |
| if (file) { | |
| dropText.textContent = file.name; | |
| uploadIcon.style.display = "none"; | |
| } | |
| }); | |
| // Appel API backend pour interprétation | |
| interpretButton.addEventListener('click', async function () { | |
| let file = fileInput.files[0]; | |
| if (!file) { | |
| resultContainer.innerHTML = `<p class="placeholder-text">⚠️ No image selected.</p>`; | |
| return; | |
| } | |
| let formData = new FormData(); | |
| formData.append("file", file); | |
| // Afficher le message de chargement pendant l'analyse | |
| resultContainer.innerHTML = `<p class="placeholder-text">⏳ Image analysis in progress...</p>`; | |
| try { | |
| const response = await fetch("/image-caption/", { | |
| method: "POST", | |
| body: formData, | |
| }); | |
| const data = await response.json(); | |
| if (data.caption) { | |
| resultContainer.innerHTML = ` | |
| <div style="display: flex; align-items: center; justify-content: flex-end; margin-bottom: 10px;"> | |
| <button id="playVoiceBtn" style=" | |
| background: linear-gradient(125deg, rgba(163, 94, 237, 0.9) 0%, rgba(65, 159, 232, 0.9) 75%); | |
| color: white; | |
| border: none; | |
| padding: 10px 16px; | |
| border-radius: 12px; | |
| cursor: pointer; | |
| font-size: 14px; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.1); | |
| transition: transform 0.2s; | |
| "> | |
| 🔊 Listen to Interpretation | |
| </button> | |
| </div> | |
| <h3 style="text-align: center; font-size: 1.5rem; font-weight: bold; color: black;">📸 Generated caption :</h3> | |
| <br> | |
| <p id="interpretationText" style="text-align: center; font-size: 1.2rem; font-weight: bold; color: black;">${data.caption}</p> | |
| `; // 🎤 Ajouter l'effet vocal | |
| const playVoiceBtn = document.getElementById("playVoiceBtn"); | |
| playVoiceBtn.addEventListener("click", function () { | |
| const textToRead = document.getElementById("interpretationText").textContent; | |
| const utterance = new SpeechSynthesisUtterance(textToRead); | |
| utterance.lang = "en-US"; // adapte ici selon la langue de l'interprétation | |
| window.speechSynthesis.speak(utterance); | |
| }); | |
| } else if (data.error) { | |
| resultContainer.innerHTML = `<p class="error-text">❌ Erreur : ${data.error}</p>`; | |
| } | |
| } catch (error) { | |
| resultContainer.innerHTML = `<p class="error-text">❌ Erreur lors de l'envoi de l'image.</p>`; | |
| } | |
| }); | |
| } | |
| //quand on clique sur quesion image --------------- | |
| function loadImagePage() { | |
| document.body.style.setProperty('--background-image', "url('qstimage.webp')"); | |
| // Créer une nouvelle structure pour éviter d’écraser les événements | |
| let appContainer = document.createElement("div"); | |
| appContainer.classList.add("app-container"); | |
| appContainer.innerHTML = ` | |
| <div class="sidebar"> | |
| <div class="logo-container"> | |
| <div class="logo-top">SMARTDOCS</div> | |
| <div class="logo-bottom">AI</div> | |
| </div> | |
| <a href="principal.html" class="home-link"> | |
| <img src="https://cdn-icons-png.flaticon.com/512/1946/1946436.png" | |
| alt="Accueil" | |
| class="home-icon" | |
| style="filter: brightness(0) saturate(100%) invert(71%) sepia(16%) saturate(4251%) hue-rotate(180deg) brightness(104%) contrast(91%);"> | |
| </a> | |
| <div class="menu-section"> | |
| <button class="menu-btn" id="interpretationButton">INTERPRETATION</button> | |
| </div> | |
| <div class="menu-section"> | |
| <div class="menu-title">DOCUMENTS</div> | |
| <button class="menu-btn" id="resumerButton">SUMMARIZE</button> | |
| <button class="menu-btn" id="traductionbutton">TRANSLATE</button> | |
| <button class="menu-btn" id="qesdocButton">DOC-QUESTIONS</button> | |
| <button class="menu-btn" id="visualisationButton">VISUALIZATION</button> | |
| </div> | |
| </div> | |
| <div class="main-content-area"> | |
| <div class="document-container"> | |
| <h1 class="document-main-title">Images Operations</h1> | |
| <h2 class="document-subtitle">IMAGES QUESTIONS 🖼️❓</h2> | |
| <div class="upload-container"> | |
| <div class="file-drop-zone" id="fileDropZone"> | |
| <label for="fileInput" class="file-upload-label"> | |
| <img src="up.png" id="uploadIcon" class="upload-icon" alt="Upload"> | |
| <span class="drop-text" id="dropText">Drop your image here or click to browse</span> | |
| </label> | |
| <input type="file" id="imageInput" class="file-input" accept=".jpg,.jpeg,.png,.gif,.bmp,.webp" hidden> | |
| </div> | |
| <div class="question-container"> | |
| <div class="question"> | |
| <input type="text" id="questionInput" placeholder="Enter your question here..."> | |
| </div> | |
| <button class="question-btn" id="sendImageQuestionBtn">Send</button> | |
| </div> | |
| </div> | |
| <div id="imageAnswer" class="results-container"> | |
| <div class="results-placeholder"> | |
| <p class="placeholder-text">The result will appear here...</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| `; | |
| // Insérer la nouvelle structure sans écraser les événements | |
| document.body.innerHTML = ""; | |
| document.body.appendChild(appContainer); | |
| // Réassocier les événements aux boutons | |
| document.getElementById('resumerButton').addEventListener('click', loadResumerPage); | |
| document.getElementById('traductionbutton').addEventListener('click', loadTraductionPage); | |
| document.getElementById('qesdocButton').addEventListener('click', loadDocPage); | |
| document.getElementById('visualisationButton').addEventListener('click', loadVisualisationPage); | |
| document.getElementById('interpretationButton').addEventListener('click', loadInterpretationPage); | |
| const fileInput = document.getElementById('imageInput'); | |
| const dropText = document.getElementById('dropText'); | |
| const uploadIcon = document.getElementById('uploadIcon'); | |
| + | |
| dropText.addEventListener('click', function(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| fileInput.click(); | |
| }); | |
| uploadIcon.addEventListener('click', function(event) { | |
| event.preventDefault(); | |
| event.stopPropagation(); | |
| fileInput.click(); | |
| }); | |
| fileInput.addEventListener('change', function(event) { | |
| let file = event.target.files[0]; | |
| if (file) { | |
| dropText.textContent = file.name; | |
| uploadIcon.style.display = "none"; | |
| } | |
| }); | |
| const sendBtn = document.getElementById("sendImageQuestionBtn"); | |
| const questionInput = document.getElementById("questionInput"); | |
| const resultContainer = document.getElementById("imageAnswer"); | |
| sendBtn.addEventListener("click", async function () { | |
| const file = fileInput.files[0]; | |
| const question = questionInput.value.trim(); | |
| if (!file || !question) { | |
| resultContainer.innerHTML = "<p class='placeholder-text'>⚠️ No question or image selected.</p>"; | |
| return; | |
| } | |
| const formData = new FormData(); | |
| formData.append("file", file); | |
| formData.append("question", question); | |
| // Afficher le message de chargement | |
| resultContainer.innerHTML = `<p class="placeholder-text" style="text-align: center; color: black; font-weight: bold;">⏳ Waiting for the answer...</p>`; | |
| try { | |
| const response = await fetch("/image-qa/", { | |
| method: "POST", | |
| body: formData | |
| }); | |
| const data = await response.json(); | |
| if (data.answer) { | |
| resultContainer.innerHTML = ` | |
| <div style="display: flex; align-items: center; justify-content: flex-end; margin-bottom: 10px;"> | |
| <button id="playVoiceBtn" style=" | |
| background: linear-gradient(125deg, rgba(163, 94, 237, 0.9) 0%, rgba(65, 159, 232, 0.9) 75%); | |
| color: white; | |
| border: none; | |
| padding: 10px 16px; | |
| border-radius: 12px; | |
| cursor: pointer; | |
| font-size: 14px; | |
| box-shadow: 0 4px 6px rgba(0,0,0,0.1); | |
| transition: transform 0.2s; | |
| "> | |
| 🔊 Listen to Answer | |
| </button> | |
| </div> | |
| <h3 style="text-align: center; font-size: 1.5rem; font-weight: bold; color: black">🧠 Generated answer :</h3> | |
| <br> | |
| <p style="text-align: center; font-size: 1.2rem; font-weight: bold; color: black;">${data.answer}</p> | |
| `; | |
| // 🎤 Ajouter l'effet vocal | |
| const playVoiceBtn = document.getElementById("playVoiceBtn"); | |
| playVoiceBtn.addEventListener("click", function () { | |
| const textToRead = data.answer; | |
| const utterance = new SpeechSynthesisUtterance(textToRead); | |
| utterance.lang = "en-US"; // adapte ici selon la langue de la réponse | |
| window.speechSynthesis.speak(utterance); | |
| }); | |
| } else { | |
| resultContainer.innerHTML = `<p class="placeholder-text">Erreur : ${data.error}</p>`; | |
| } | |
| } catch (error) { | |
| resultContainer.innerHTML = `<p class="placeholder-text">Erreur lors de l'envoi : ${error.message}</p>`; | |
| } | |
| }); | |
| } |