“shubhamdhamal”
Deploy Flask app with Docker
7644eac
/**
* Main JavaScript file for the AI Learning Path Generator
* Handles client-side interactivity for the web interface
*/
// Wait for DOM to be fully loaded
document.addEventListener('DOMContentLoaded', function() {
// Form submission handling for path generator
const pathForm = document.getElementById('pathGeneratorForm');
if (pathForm) {
setupPathGenerator(pathForm);
}
// Question handling for result page
const askButton = document.getElementById('askButton');
if (askButton) {
setupQuestionAsking(askButton);
}
// Initialize tooltips and other UI elements
initUI();
});
/**
* Set up path generator form submission
* @param {HTMLElement} form - The form element
*/
function setupPathGenerator(form) {
const loadingSpinner = document.getElementById('loadingSpinner');
form.addEventListener('submit', function(e) {
e.preventDefault();
// Show loading spinner
if (loadingSpinner) {
loadingSpinner.style.display = 'block';
}
// Gather form data
const formData = new FormData(form);
formData.append('type', 'human');
// Convert FormData to plain object for logging
const formDataObj = {};
formData.forEach((value, key) => {
formDataObj[key] = value;
});
console.log('Submitting form data:', formDataObj);
// Submit form data via fetch API
fetch('/generate', {
method: 'POST',
body: formData, // Let the browser set the correct Content-Type with boundary
// Don't set Content-Type header when sending FormData, let the browser handle it
})
.then(response => response.json())
.then(data => {
// Hide loading spinner
if (loadingSpinner) {
loadingSpinner.style.display = 'none';
}
if (data.success) {
// Redirect to result page if successful
window.location.href = data.redirect;
} else {
// Show error message
showAlert('Error: ' + data.message, 'error');
}
})
.catch(error => {
// Hide loading spinner
if (loadingSpinner) {
loadingSpinner.style.display = 'none';
}
console.error('Error:', error);
showAlert('An error occurred. Please try again.', 'error');
});
});
}
/**
* Set up question asking functionality
* @param {HTMLElement} button - The ask button element
*/
function setupQuestionAsking(button) {
const questionInput = document.getElementById('questionInput');
const questionSpinner = document.getElementById('questionSpinner');
const answerContainer = document.getElementById('answerContainer');
const answerText = document.getElementById('answerText');
button.addEventListener('click', function() {
const question = questionInput.value.trim();
if (!question) {
showAlert('Please enter a question', 'warning');
return;
}
// Show loading spinner
if (questionSpinner) {
questionSpinner.style.display = 'block';
}
// Get path information from the page
const pathId = document.querySelector('[data-path-id]')?.dataset.pathId;
const topic = document.querySelector('[data-path-topic]')?.dataset.pathTopic;
// Prepare request data
const requestData = {
type: "human",
question: question,
path_id: pathId,
topic: topic
};
// Submit question via fetch API
fetch('/api/ask', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(requestData)
})
.then(response => response.json())
.then(data => {
// Hide loading spinner
if (questionSpinner) {
questionSpinner.style.display = 'none';
}
if (data.success !== false) {
// Show answer container
if (answerContainer) {
answerContainer.classList.remove('hidden');
}
if (answerText) {
answerText.textContent = data.answer;
}
} else {
// Show error message
showAlert('Error: ' + data.message, 'error');
}
})
.catch(error => {
// Hide loading spinner
if (questionSpinner) {
questionSpinner.style.display = 'none';
}
console.error('Error:', error);
showAlert('An error occurred. Please try again.', 'error');
});
});
}
/**
* Initialize UI components
*/
function initUI() {
// Add smooth scrolling for anchor links
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
window.scrollTo({
top: target.offsetTop,
behavior: 'smooth'
});
}
});
});
// Add fade-in animations for elements
const fadeElems = document.querySelectorAll('.fade-in');
fadeElems.forEach((elem, index) => {
setTimeout(() => {
elem.style.opacity = '1';
elem.style.transform = 'translateY(0)';
}, 100 * index);
});
}
/**
* Show an alert message
* @param {string} message - The message to display
* @param {string} type - The type of alert (success, error, warning, info)
*/
function showAlert(message, type = 'info') {
// Check if an alert container exists, otherwise create one
let alertContainer = document.getElementById('alertContainer');
if (!alertContainer) {
alertContainer = document.createElement('div');
alertContainer.id = 'alertContainer';
alertContainer.style.position = 'fixed';
alertContainer.style.top = '1rem';
alertContainer.style.right = '1rem';
alertContainer.style.zIndex = '9999';
document.body.appendChild(alertContainer);
}
// Create the alert element
const alert = document.createElement('div');
alert.className = 'alert-message fade-in';
alert.style.padding = '0.75rem 1rem';
alert.style.marginBottom = '0.5rem';
alert.style.borderRadius = '0.375rem';
alert.style.boxShadow = '0 2px 5px rgba(0,0,0,0.1)';
alert.style.opacity = '0';
alert.style.transform = 'translateY(10px)';
alert.style.transition = 'opacity 0.3s ease, transform 0.3s ease';
// Set styles based on type
switch (type) {
case 'success':
alert.style.backgroundColor = '#d1fae5';
alert.style.color = '#065f46';
break;
case 'error':
alert.style.backgroundColor = '#fee2e2';
alert.style.color = '#991b1b';
break;
case 'warning':
alert.style.backgroundColor = '#fef3c7';
alert.style.color = '#92400e';
break;
default: // info
alert.style.backgroundColor = '#e0f2fe';
alert.style.color = '#0369a1';
}
// Set the message
alert.textContent = message;
// Add a close button
const closeButton = document.createElement('span');
closeButton.innerHTML = '×';
closeButton.style.float = 'right';
closeButton.style.cursor = 'pointer';
closeButton.style.fontWeight = 'bold';
closeButton.style.marginLeft = '1rem';
closeButton.addEventListener('click', () => {
alert.remove();
});
alert.prepend(closeButton);
// Add the alert to the container
alertContainer.appendChild(alert);
// Trigger animation
setTimeout(() => {
alert.style.opacity = '1';
alert.style.transform = 'translateY(0)';
}, 10);
// Auto-remove after 5 seconds
setTimeout(() => {
alert.style.opacity = '0';
alert.style.transform = 'translateY(-10px)';
// Remove from DOM after animation completes
setTimeout(() => {
alert.remove();
}, 300);
}, 5000);
}