ikraamkb's picture
Update static/appS.js
eb457e5 verified
raw
history blame
10.7 kB
document.addEventListener('DOMContentLoaded', () => {
// UI Elements
const GotitB = document.querySelector(".explainChoix button");
const explain = document.querySelector(".explainChoix");
const SummarizeInput = document.querySelector(".SummarizeInput");
const CaptionInput = document.querySelector(".CaptionInput");
const fileUpload = document.getElementById('file-upload');
const imageUpload = document.getElementById('image-upload');
const fileBtn = document.getElementById('file-btn');
const imageBtn = document.getElementById('image-btn');
const convo = document.querySelector('.convo');
// Hide explanation after click
GotitB.addEventListener("click", () => {
explain.style.opacity = "0";
});
// Handle mode switching
document.querySelectorAll('.select-options input[type="radio"]').forEach(radio => {
radio.addEventListener('change', (e) => {
if (e.target.checked) {
const selectedValue = e.target.value;
if (selectedValue === "Summarize") {
SummarizeInput.classList.add("active");
SummarizeInput.classList.remove("innactive");
CaptionInput.classList.remove("active");
CaptionInput.classList.add("innactive");
} else {
SummarizeInput.classList.add("innactive");
SummarizeInput.classList.remove("active");
CaptionInput.classList.remove("innactive");
CaptionInput.classList.add("active");
}
}
});
});
// File upload handlers
fileBtn.addEventListener('click', () => fileUpload.click());
imageBtn.addEventListener('click', () => imageUpload.click());
// Send button handlers
document.querySelectorAll('.sendingQA').forEach(button => {
button.addEventListener('click', async () => {
const isSummarizeMode = document.querySelector('input[name="option"]:checked').value === 'Summarize';
if (isSummarizeMode) {
await handleSummarize();
} else {
await handleCaption();
}
});
});
// Handle document summarization
async function handleSummarize() {
const file = fileUpload.files[0];
if (!file) {
displayError('Please upload a document first');
return;
}
const length = document.querySelector('input[name="optionS"]:checked')?.value || 'medium';
try {
// Show loading state
convo.innerHTML = '';
displayFileInfo(file.name, 'document');
displayThinkingMessage();
// Call API
const result = await summarizeDocument(file, length);
// Display results
displaySummaryResult(file.name, result.summary, result.audio_url, result.pdf_url);
} catch (error) {
displayError(error.message || 'Failed to summarize document');
}
}
// Handle image captioning
async function handleCaption() {
const file = imageUpload.files[0];
if (!file) {
displayError('Please upload an image first');
return;
}
try {
// Show loading state
convo.innerHTML = '';
displayFileInfo(file.name, 'image');
displayThinkingMessage();
// Call API
const result = await captionImage(file);
// Display results
displayCaptionResult(file.name, result.answer, result.audio);
} catch (error) {
displayError(error.message || 'Failed to generate caption');
}
}
// API Functions
async function summarizeDocument(file, length) {
const formData = new FormData();
formData.append('file', file);
formData.append('length', length);
const response = await fetch('/summarize/', {
method: 'POST',
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Summarization failed');
}
return await response.json();
}
async function captionImage(file) {
const formData = new FormData();
formData.append('file', file);
const response = await fetch('/imagecaption/', {
method: 'POST',
body: formData
});
if (!response.ok) {
const error = await response.json();
throw new Error(error.error || 'Captioning failed');
}
return await response.json();
}
// UI Helper Functions
function displayFileInfo(filename, type) {
const bubble = document.createElement('div');
bubble.className = 'bubble right';
bubble.innerHTML = `
<div class="label">You</div>
<div class="text">${type === 'document' ? '📄' : '🖼️'} ${filename}</div>
`;
convo.appendChild(bubble);
}
function displayThinkingMessage() {
const bubble = document.createElement('div');
bubble.className = 'bubble left';
bubble.innerHTML = `
<div class="label">Aidan</div>
<div class="text">
<div style="display:flex;align-items:center;gap:8px">
<span>Processing your ${document.querySelector('input[name="option"]:checked').value.toLowerCase()}...</span>
<div class="loader"></div>
</div>
</div>
`;
convo.appendChild(bubble);
convo.scrollTop = convo.scrollHeight;
}
function displaySummaryResult(filename, summary, audioUrl, pdfUrl) {
// Remove thinking message
convo.removeChild(convo.lastChild);
const bubble = document.createElement('div');
bubble.className = 'bubble left';
bubble.innerHTML = `
<div class="label">Aidan</div>
<div class="text">
<strong>Summary:</strong><br><br>
${summary.replace(/\n/g, '<br>')}
<div class="action-buttons" style="margin-top: 10px; display: flex; gap: 10px;">
${audioUrl ? `
<button class="audio-control" data-audio="${audioUrl}">
<i class="fa-solid fa-volume-high"></i> Audio
</button>` : ''}
${pdfUrl ? `
<a href="${pdfUrl}" download="${filename.split('.')[0]}_summary.pdf" class="download-btn">
<i class="fa-solid fa-download"></i> PDF
</a>` : ''}
</div>
</div>
`;
convo.appendChild(bubble);
setupAudioControls();
convo.scrollTop = convo.scrollHeight;
}
function displayCaptionResult(filename, caption, audioUrl) {
// Remove thinking message
convo.removeChild(convo.lastChild);
const bubble = document.createElement('div');
bubble.className = 'bubble left';
bubble.innerHTML = `
<div class="label">Aidan</div>
<div class="text">
<strong>Caption:</strong><br><br>
${caption}
${audioUrl ? `
<div class="action-buttons" style="margin-top: 10px;">
<button class="audio-control" data-audio="${audioUrl}">
<i class="fa-solid fa-volume-high"></i> Audio
</button>
</div>` : ''}
</div>
`;
convo.appendChild(bubble);
setupAudioControls();
convo.scrollTop = convo.scrollHeight;
}
function setupAudioControls() {
document.querySelectorAll('.audio-control').forEach(button => {
const audioUrl = button.getAttribute('data-audio');
const audio = new Audio(audioUrl);
const icon = button.querySelector('i');
button.addEventListener('click', () => {
if (audio.paused) {
audio.play();
icon.classList.remove('fa-volume-xmark');
icon.classList.add('fa-volume-high');
} else {
audio.pause();
icon.classList.remove('fa-volume-high');
icon.classList.add('fa-volume-xmark');
}
});
});
}
function displayError(message) {
const bubble = document.createElement('div');
bubble.className = 'bubble left';
bubble.innerHTML = `
<div class="label">Aidan</div>
<div class="text" style="color: #ef4444;">
⚠️ ${message}
</div>
`;
convo.appendChild(bubble);
convo.scrollTop = convo.scrollHeight;
}
// Add loader CSS
const style = document.createElement('style');
style.textContent = `
.loader {
border: 2px solid #f3f3f3;
border-top: 2px solid #3b82f6;
border-radius: 50%;
width: 16px;
height: 16px;
animation: spin 1s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.download-btn, .audio-control {
display: inline-flex;
align-items: center;
gap: 5px;
padding: 5px 10px;
background: #3b82f6;
color: white;
border: none;
border-radius: 5px;
cursor: pointer;
text-decoration: none;
font-size: 14px;
}
.download-btn:hover, .audio-control:hover {
background: #2563eb;
}
.bubble {
max-width: 80%;
padding: 12px 16px;
margin: 8px 0;
border-radius: 18px;
position: relative;
clear: both;
}
.bubble.left {
background: #f1f1f1;
float: left;
margin-right: auto;
}
.bubble.right {
background: #3b82f6;
color: white;
float: right;
margin-left: auto;
}
.label {
font-weight: bold;
font-size: 12px;
margin-bottom: 4px;
}
`;
document.head.appendChild(style);
});