// API Configuration const API_URL = 'https://nolanzandi-virtual-data-analyst.hf.space'; const PREDICT_ENDPOINT = `${API_URL}/api/predict`; const SAMPLE_ENDPOINT = `${API_URL}/api/sample`; // File Upload and API Integration async function handleFileUpload(file) { try { // Show loading state document.querySelector('.upload-icon').style.display = 'none'; document.querySelector('.loading-spinner').style.display = 'block'; document.querySelector('.progress-bar').style.display = 'block'; // Create FormData const formData = new FormData(); formData.append('file', file); // Update file info updateFileInfo(file); // Simulate progress while actually uploading const progressInterval = simulateProgress(); // Make API request const response = await fetch(API_URL, { method: 'POST', body: formData }); if (!response.ok) { throw new Error('API request failed'); } const data = await response.json(); // Clear progress simulation clearInterval(progressInterval); // Show success state showSuccessState(); // Handle API response handleApiResponse(data); } catch (error) { console.error('Error:', error); showErrorState(error.message); } } function updateFileInfo(file) { const fileInfo = document.getElementById('fileInfo'); const fileName = fileInfo.querySelector('.file-name'); const fileSize = fileInfo.querySelector('.file-size'); const fileIcon = fileInfo.querySelector('.file-type-icon'); const fileType = file.name.split('.').pop().toLowerCase(); const iconClass = getFileTypeIcon(fileType); fileIcon.className = `file-type-icon fas ${iconClass}`; fileName.textContent = file.name; fileSize.textContent = formatFileSize(file.size); fileInfo.classList.remove('hidden'); } function simulateProgress() { const progressBar = document.querySelector('.progress-bar-fill'); let progress = 0; return setInterval(() => { if (progress < 90) { // Only go up to 90% until we get actual completion progress += 5; progressBar.style.width = `${progress}%`; } }, 100); } function showSuccessState() { document.querySelector('.loading-spinner').style.display = 'none'; document.querySelector('.success-checkmark').style.display = 'block'; document.querySelector('.progress-bar-fill').style.width = '100%'; setTimeout(() => { resetUploadState(); }, 2000); } function showErrorState(message) { // Reset upload UI resetUploadState(); // Show error message const errorDiv = document.createElement('div'); errorDiv.className = 'text-red-500 mt-4'; errorDiv.innerHTML = `${message}`; document.querySelector('.drop-zone').appendChild(errorDiv); setTimeout(() => { errorDiv.remove(); }, 5000); } function resetUploadState() { document.querySelector('.success-checkmark').style.display = 'none'; document.querySelector('.upload-icon').style.display = 'block'; document.querySelector('.progress-bar').style.display = 'none'; document.querySelector('.progress-bar-fill').style.width = '0%'; document.getElementById('fileInfo').classList.add('hidden'); } function handleSampleDataClick(datasetName) { // Show loading state in results section const resultsSection = document.getElementById('results'); const resultsLoading = document.getElementById('resultsLoading'); const resultsContent = document.getElementById('resultsContent'); const resultsError = document.getElementById('resultsError'); resultsSection.classList.remove('hidden'); resultsLoading.classList.remove('hidden'); resultsContent.classList.add('hidden'); resultsError.classList.add('hidden'); // Simulate API delay setTimeout(() => { try { // Mock data based on dataset type const mockData = datasetName === 'marketing_campaign' ? { statistics: { rows: 10000, columns: 15, missing_values: 120, data_types: ['numeric', 'categorical', 'datetime'] }, preview: { columns: ['Campaign ID', 'Customer ID', 'Response', 'Channel'], data: [ ['CAM001', 'C001', 'Converted', 'Email'], ['CAM001', 'C002', 'No Response', 'SMS'], ['CAM002', 'C003', 'Converted', 'Social Media'] ] }, visualizations: [ { title: 'Response Rate by Channel', description: 'Conversion rates across different marketing channels', image_url: 'https://via.placeholder.com/400x300' }, { title: 'Campaign Performance', description: 'Success metrics for each campaign', image_url: 'https://via.placeholder.com/400x300' } ], insights: [ { title: 'Best Performing Channel', description: 'Email campaigns show highest conversion rate at 28%' }, { title: 'Optimal Send Time', description: 'Campaigns sent between 2 PM - 4 PM have better engagement' } ] } : { statistics: { rows: 50000, columns: 12, missing_values: 85, data_types: ['numeric', 'categorical', 'datetime'] }, preview: { columns: ['Order ID', 'Product', 'Quantity', 'Price'], data: [ ['ORD001', 'Laptop', '1', '$999.99'], ['ORD002', 'Mouse', '2', '$29.99'], ['ORD003', 'Monitor', '1', '$299.99'] ] }, visualizations: [ { title: 'Sales by Category', description: 'Distribution of sales across product categories', image_url: 'https://via.placeholder.com/400x300' }, { title: 'Monthly Revenue', description: 'Revenue trends over the past 12 months', image_url: 'https://via.placeholder.com/400x300' } ], insights: [ { title: 'Top Products', description: 'Electronics category generates 45% of total revenue' }, { title: 'Customer Behavior', description: 'Average order value increased by 15% in Q4' } ] }; handleApiResponse(mockData); } catch (error) { console.error('Error:', error); showErrorState('Failed to process sample dataset'); } }, 1000); // 1 second delay to show loading state } function handleApiResponse(data) { const resultsSection = document.getElementById('results'); const resultsLoading = document.getElementById('resultsLoading'); const resultsContent = document.getElementById('resultsContent'); const resultsError = document.getElementById('resultsError'); // Show results section resultsSection.classList.remove('hidden'); resultsLoading.classList.add('hidden'); resultsError.classList.add('hidden'); resultsContent.classList.remove('hidden'); // Update Basic Statistics updateBasicStats(data.statistics); // Update Data Preview updateDataPreview(data.preview); // Update Visualizations updateVisualizations(data.visualizations); // Update Insights updateInsights(data.insights); } function updateBasicStats(statistics) { const statsContainer = document.getElementById('basicStats'); statsContainer.innerHTML = ''; const stats = [ { label: 'Rows', value: statistics.rows, icon: 'fa-list' }, { label: 'Columns', value: statistics.columns, icon: 'fa-columns' }, { label: 'Missing Values', value: statistics.missing_values, icon: 'fa-exclamation-triangle' }, { label: 'Data Types', value: statistics.data_types.length, icon: 'fa-code' } ]; stats.forEach(stat => { const statDiv = document.createElement('div'); statDiv.className = 'bg-gray-50 rounded-lg p-4'; statDiv.innerHTML = `
${viz.description}
`; container.appendChild(vizDiv); }); } function updateInsights(insights) { const insightsList = document.getElementById('insights'); insightsList.innerHTML = ''; insights.forEach(insight => { const li = document.createElement('li'); li.className = 'bg-blue-50 rounded-lg p-4'; li.innerHTML = `${insight.description}