mirror of
https://github.com/thecyberlearn/quantum-ai-v3.git
synced 2026-08-19 00:52:57 +00:00
Replace demo JavaScript implementation with real backend processing: - Remove fake analyzeData() function that only updated frontend - Add real AJAX submission to /agents/data-analyzer/process/ endpoint - Implement proper polling for results using request ID - Add displayResults() function to handle backend responses - Update wallet balance from server response to ensure persistence - Remove generateSampleAnalysis() demo function - Fix wallet balance to persist across page navigation This resolves the issue where wallet deduction would revert when navigating to other pages, as the frontend was using demo mode instead of actual database transactions. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
778 lines
27 KiB
HTML
778 lines
27 KiB
HTML
{% extends 'base.html' %}
|
|
{% load static %}
|
|
|
|
{% block title %}Data Analyzer Agent - NetCop AI Hub{% endblock %}
|
|
|
|
{% block extra_css %}
|
|
<style>
|
|
* {
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
/* Override main-container for full-width sections */
|
|
.main-container {
|
|
max-width: none;
|
|
padding: 0;
|
|
margin-top: 0;
|
|
}
|
|
|
|
/* Page background */
|
|
.data-analyzer-page {
|
|
background: linear-gradient(135deg, #f6f8ff 0%, #e8f0fe 50%, #f0f7ff 100%);
|
|
min-height: calc(100vh - 80px);
|
|
padding: clamp(20px, 5vw, 40px);
|
|
width: 100vw;
|
|
margin-left: calc(-50vw + 50%);
|
|
}
|
|
|
|
.container {
|
|
max-width: 1280px;
|
|
margin: 0 auto;
|
|
padding: 0 clamp(16px, 4vw, 24px);
|
|
}
|
|
|
|
/* Main grid layout */
|
|
.main-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(min(350px, 100%), 1fr));
|
|
gap: clamp(16px, 4vw, 24px);
|
|
align-items: start;
|
|
}
|
|
|
|
/* Card styles with glassmorphism */
|
|
.card {
|
|
background: rgba(255, 255, 255, 0.9);
|
|
border-radius: clamp(12px, 3vw, 16px);
|
|
padding: clamp(16px, 4vw, 24px);
|
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
backdrop-filter: blur(20px);
|
|
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
|
margin-bottom: clamp(16px, 4vw, 24px);
|
|
}
|
|
|
|
.section-title {
|
|
font-size: clamp(16px, 4vw, 18px);
|
|
font-weight: 600;
|
|
color: #1f2937;
|
|
margin-bottom: clamp(12px, 3vw, 16px);
|
|
}
|
|
|
|
/* Form inputs */
|
|
.form-input {
|
|
width: 100%;
|
|
padding: clamp(12px, 3vw, 16px) clamp(16px, 4vw, 20px);
|
|
border: 2px solid #e5e7eb;
|
|
border-radius: clamp(8px, 2vw, 12px);
|
|
font-size: clamp(14px, 3.5vw, 16px);
|
|
transition: border-color 0.2s ease;
|
|
min-height: 48px;
|
|
margin-bottom: clamp(12px, 3vw, 16px);
|
|
}
|
|
|
|
.form-input:focus {
|
|
outline: none;
|
|
border-color: #10b981;
|
|
}
|
|
|
|
.help-text {
|
|
font-size: clamp(12px, 3vw, 14px);
|
|
color: #6b7280;
|
|
}
|
|
|
|
/* File upload zone */
|
|
.file-upload-zone {
|
|
border: 2px dashed #d1d5db;
|
|
border-radius: clamp(12px, 3vw, 16px);
|
|
padding: clamp(24px, 6vw, 40px);
|
|
text-align: center;
|
|
transition: all 0.3s ease;
|
|
background: #f9fafb;
|
|
cursor: pointer;
|
|
margin-bottom: clamp(12px, 3vw, 16px);
|
|
}
|
|
|
|
.file-upload-zone.dragover {
|
|
border-color: #10b981;
|
|
background: #f0fdf4;
|
|
}
|
|
|
|
.file-upload-zone:hover {
|
|
border-color: #10b981;
|
|
background: #f0fdf4;
|
|
}
|
|
|
|
.file-preview {
|
|
background: #f0fdf4;
|
|
border: 1px solid #86efac;
|
|
border-radius: 8px;
|
|
padding: 12px;
|
|
margin-top: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
}
|
|
|
|
/* Radio button grids */
|
|
.radio-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(min(180px, 100%), 1fr));
|
|
gap: clamp(8px, 2vw, 12px);
|
|
}
|
|
|
|
.radio-option {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: clamp(8px, 2vw, 12px);
|
|
padding: clamp(12px, 3vw, 16px);
|
|
border: 2px solid #e5e7eb;
|
|
border-radius: clamp(8px, 2vw, 12px);
|
|
cursor: pointer;
|
|
background: white;
|
|
transition: all 0.2s ease;
|
|
min-height: 44px;
|
|
}
|
|
|
|
.radio-option.selected {
|
|
border-color: #10b981;
|
|
background: #f0fdf4;
|
|
}
|
|
|
|
.radio-option input[type="radio"] {
|
|
margin: 0;
|
|
}
|
|
|
|
/* Processing status */
|
|
.processing-status {
|
|
padding: clamp(16px, 4vw, 20px);
|
|
background: #f0fdf4;
|
|
border: 1px solid #10b981;
|
|
border-radius: clamp(8px, 2vw, 12px);
|
|
color: #047857;
|
|
font-weight: 600;
|
|
text-align: center;
|
|
margin-bottom: clamp(16px, 4vw, 24px);
|
|
}
|
|
|
|
/* Results card */
|
|
.results-card {
|
|
background: rgba(255, 255, 255, 0.9);
|
|
border-radius: 16px;
|
|
padding: 24px;
|
|
border: 1px solid rgba(255, 255, 255, 0.3);
|
|
backdrop-filter: blur(20px);
|
|
box-shadow: 0 8px 25px rgba(0, 0, 0, 0.1);
|
|
margin-top: 24px;
|
|
}
|
|
|
|
.results-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.results-content {
|
|
background: #f8fafc;
|
|
border: 1px solid #e2e8f0;
|
|
border-radius: 12px;
|
|
padding: 24px;
|
|
margin-bottom: 20px;
|
|
white-space: pre-line;
|
|
line-height: 1.7;
|
|
color: #374151;
|
|
font-size: 15px;
|
|
}
|
|
|
|
.action-buttons {
|
|
display: flex;
|
|
gap: 12px;
|
|
margin-top: 20px;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
/* Button styles */
|
|
.btn {
|
|
padding: clamp(12px, 3vw, 16px) clamp(20px, 5vw, 32px);
|
|
border: none;
|
|
border-radius: clamp(8px, 2vw, 12px);
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
font-size: clamp(14px, 3.5vw, 16px);
|
|
min-height: 48px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
transition: transform 0.1s ease;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.btn-primary {
|
|
background: linear-gradient(135deg, #10b981 0%, #059669 100%);
|
|
color: white;
|
|
flex: 1;
|
|
min-width: 120px;
|
|
}
|
|
|
|
.btn-secondary {
|
|
background: white;
|
|
color: #374151;
|
|
border: 2px solid #e5e7eb;
|
|
flex: 1;
|
|
min-width: 120px;
|
|
}
|
|
|
|
.btn:hover {
|
|
transform: translateY(-1px);
|
|
}
|
|
|
|
.btn:disabled {
|
|
background: #9ca3af;
|
|
cursor: not-allowed;
|
|
transform: none;
|
|
}
|
|
|
|
/* Wallet sidebar */
|
|
.wallet-section {
|
|
position: sticky;
|
|
top: 20px;
|
|
}
|
|
|
|
.wallet-balance {
|
|
font-size: clamp(24px, 6vw, 28px);
|
|
font-weight: 700;
|
|
color: #1f2937;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.balance-label {
|
|
font-size: clamp(14px, 3.5vw, 16px);
|
|
color: #6b7280;
|
|
margin-bottom: clamp(16px, 4vw, 20px);
|
|
}
|
|
|
|
.process-btn {
|
|
width: 100%;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.usage-info {
|
|
padding: 16px;
|
|
background: rgba(16, 185, 129, 0.1);
|
|
border-radius: 12px;
|
|
border: 1px solid rgba(16, 185, 129, 0.2);
|
|
}
|
|
|
|
.usage-info h4 {
|
|
margin: 0 0 8px 0;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: #047857;
|
|
}
|
|
|
|
.usage-info ul {
|
|
margin: 0;
|
|
font-size: 12px;
|
|
color: #374151;
|
|
line-height: 1.4;
|
|
list-style: none;
|
|
padding-left: 0;
|
|
}
|
|
|
|
.usage-info li {
|
|
margin: 4px 0;
|
|
padding-left: 16px;
|
|
position: relative;
|
|
}
|
|
|
|
.usage-info li::before {
|
|
content: "•";
|
|
position: absolute;
|
|
left: 0;
|
|
color: #10b981;
|
|
}
|
|
|
|
/* Responsive */
|
|
@media (max-width: 768px) {
|
|
.main-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.radio-grid {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
|
|
.action-buttons {
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
</style>
|
|
{% endblock %}
|
|
|
|
{% block content %}
|
|
<div class="data-analyzer-page">
|
|
<div class="container">
|
|
<!-- Main Content Grid -->
|
|
<div class="main-grid">
|
|
<!-- Input Form -->
|
|
<div>
|
|
<!-- File Upload Section -->
|
|
<div class="card">
|
|
<h3 class="section-title">📁 Upload Your Data File</h3>
|
|
|
|
<div class="file-upload-zone" id="fileUploadZone" onclick="document.getElementById('fileInput').click()">
|
|
<div style="font-size: clamp(32px, 8vw, 48px); margin-bottom: 12px;">📊</div>
|
|
<div style="font-size: clamp(16px, 4vw, 18px); font-weight: 600; color: #374151; margin-bottom: 8px;">
|
|
Choose or drag your data file here
|
|
</div>
|
|
<div style="font-size: clamp(14px, 3.5vw, 16px); color: #6b7280;">
|
|
Supports PDF, CSV, Excel files (up to 10MB)
|
|
</div>
|
|
</div>
|
|
|
|
<input
|
|
type="file"
|
|
id="fileInput"
|
|
accept=".pdf,.csv,.xlsx,.xls"
|
|
style="display: none;"
|
|
/>
|
|
|
|
<div id="filePreview" class="file-preview" style="display: none;">
|
|
<div style="font-size: 24px;">📄</div>
|
|
<div style="flex: 1;">
|
|
<div style="font-weight: 600; color: #1f2937;" id="fileName"></div>
|
|
<div style="font-size: 14px; color: #6b7280;" id="fileSize"></div>
|
|
</div>
|
|
<button type="button" onclick="removeFile()" style="
|
|
background: #ef4444;
|
|
color: white;
|
|
border: none;
|
|
border-radius: 4px;
|
|
padding: 4px 8px;
|
|
cursor: pointer;
|
|
font-size: 12px;
|
|
">
|
|
Remove
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Analysis Type Selection -->
|
|
<div class="card">
|
|
<h3 class="section-title">🔍 Analysis Type</h3>
|
|
|
|
<div class="radio-grid">
|
|
<label class="radio-option selected" data-value="summary">
|
|
<input type="radio" name="analysisType" value="summary" checked />
|
|
<div style="font-size: clamp(16px, 4vw, 20px);">📋</div>
|
|
<div>
|
|
<div style="font-weight: 600; margin-bottom: clamp(2px, 1vw, 4px); font-size: clamp(14px, 3.5vw, 16px);">
|
|
Summary Analysis
|
|
</div>
|
|
<div style="font-size: clamp(12px, 3vw, 14px); color: #6b7280;">
|
|
Quick overview and key insights
|
|
</div>
|
|
</div>
|
|
</label>
|
|
|
|
<label class="radio-option" data-value="detailed">
|
|
<input type="radio" name="analysisType" value="detailed" />
|
|
<div style="font-size: clamp(16px, 4vw, 20px);">📈</div>
|
|
<div>
|
|
<div style="font-weight: 600; margin-bottom: clamp(2px, 1vw, 4px); font-size: clamp(14px, 3.5vw, 16px);">
|
|
Detailed Analysis
|
|
</div>
|
|
<div style="font-size: clamp(12px, 3vw, 14px); color: #6b7280;">
|
|
Comprehensive statistical analysis
|
|
</div>
|
|
</div>
|
|
</label>
|
|
|
|
<label class="radio-option" data-value="statistical">
|
|
<input type="radio" name="analysisType" value="statistical" />
|
|
<div style="font-size: clamp(16px, 4vw, 20px);">📊</div>
|
|
<div>
|
|
<div style="font-weight: 600; margin-bottom: clamp(2px, 1vw, 4px); font-size: clamp(14px, 3.5vw, 16px);">
|
|
Statistical Analysis
|
|
</div>
|
|
<div style="font-size: clamp(12px, 3vw, 14px); color: #6b7280;">
|
|
Advanced statistics and trends
|
|
</div>
|
|
</div>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Processing Status -->
|
|
<div id="processingStatus" class="processing-status" style="display: none;">
|
|
<div style="font-size: clamp(16px, 4vw, 18px); margin-bottom: 8px;">
|
|
⏳ Processing...
|
|
</div>
|
|
<div style="font-size: clamp(14px, 3.5vw, 16px);" id="statusText">
|
|
Analyzing your data file...
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Results -->
|
|
<div id="analysisResults" class="results-card" style="display: none;">
|
|
<div class="results-header">
|
|
<div style="font-size: 24px;">✅</div>
|
|
<h3 style="font-size: 20px; font-weight: 600; color: #1f2937; margin: 0;">
|
|
Data Analysis Results
|
|
</h3>
|
|
<div style="
|
|
background: #10b981;
|
|
color: white;
|
|
padding: 6px 12px;
|
|
border-radius: 6px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
margin-left: auto;
|
|
">
|
|
✅ Complete
|
|
</div>
|
|
</div>
|
|
|
|
<div class="results-content" id="analysisContent">
|
|
<!-- Analysis data will be displayed here -->
|
|
</div>
|
|
|
|
<div class="action-buttons">
|
|
<button onclick="copyAnalysisReport()" class="btn btn-primary">
|
|
📋 Copy Report
|
|
</button>
|
|
<button onclick="downloadAnalysisReport()" class="btn btn-secondary">
|
|
💾 Download Report
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Wallet Sidebar -->
|
|
<div class="wallet-section">
|
|
<div class="card">
|
|
<h3 class="section-title">💳 Your Wallet</h3>
|
|
|
|
<div class="wallet-balance" id="walletBalance">{{ user.wallet_balance|floatformat:2 }} AED</div>
|
|
<div class="balance-label">Available Balance</div>
|
|
|
|
<button
|
|
class="btn btn-primary process-btn"
|
|
id="processButton"
|
|
onclick="analyzeData()"
|
|
>
|
|
📊 Analyze Data (5.00 AED)
|
|
</button>
|
|
</div>
|
|
|
|
<div class="usage-info">
|
|
<h4>💡 How it works</h4>
|
|
<ul>
|
|
<li>Upload PDF, CSV, or Excel files</li>
|
|
<li>Choose your analysis depth</li>
|
|
<li>Get AI-powered insights</li>
|
|
<li>Download comprehensive reports</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block extra_js %}
|
|
<script>
|
|
let selectedFile = null;
|
|
|
|
// File upload handling
|
|
const fileInput = document.getElementById('fileInput');
|
|
const fileUploadZone = document.getElementById('fileUploadZone');
|
|
const filePreview = document.getElementById('filePreview');
|
|
|
|
// Handle file input change
|
|
fileInput.addEventListener('change', function(e) {
|
|
if (e.target.files.length > 0) {
|
|
selectedFile = e.target.files[0];
|
|
showFilePreview(selectedFile);
|
|
}
|
|
});
|
|
|
|
// Drag and drop functionality
|
|
fileUploadZone.addEventListener('dragover', function(e) {
|
|
e.preventDefault();
|
|
fileUploadZone.classList.add('dragover');
|
|
});
|
|
|
|
fileUploadZone.addEventListener('dragleave', function(e) {
|
|
e.preventDefault();
|
|
fileUploadZone.classList.remove('dragover');
|
|
});
|
|
|
|
fileUploadZone.addEventListener('drop', function(e) {
|
|
e.preventDefault();
|
|
fileUploadZone.classList.remove('dragover');
|
|
|
|
const files = e.dataTransfer.files;
|
|
if (files.length > 0) {
|
|
const file = files[0];
|
|
if (isValidFile(file)) {
|
|
selectedFile = file;
|
|
fileInput.files = files;
|
|
showFilePreview(file);
|
|
} else {
|
|
showToast('Please select a valid data file (PDF, CSV, Excel)', 'error');
|
|
}
|
|
}
|
|
});
|
|
|
|
// Show file preview
|
|
function showFilePreview(file) {
|
|
document.getElementById('fileName').textContent = file.name;
|
|
document.getElementById('fileSize').textContent = formatFileSize(file.size);
|
|
filePreview.style.display = 'flex';
|
|
fileUploadZone.style.display = 'none';
|
|
}
|
|
|
|
// Remove file
|
|
function removeFile() {
|
|
selectedFile = null;
|
|
fileInput.value = '';
|
|
filePreview.style.display = 'none';
|
|
fileUploadZone.style.display = 'block';
|
|
}
|
|
|
|
// Validate file type
|
|
function isValidFile(file) {
|
|
const validTypes = [
|
|
'application/pdf',
|
|
'text/csv',
|
|
'application/vnd.ms-excel',
|
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
|
|
];
|
|
return validTypes.includes(file.type) || file.name.match(/\.(pdf|csv|xlsx|xls)$/i);
|
|
}
|
|
|
|
// Format file size
|
|
function formatFileSize(bytes) {
|
|
if (bytes === 0) return '0 Bytes';
|
|
const k = 1024;
|
|
const sizes = ['Bytes', 'KB', 'MB', 'GB'];
|
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
|
|
}
|
|
|
|
// Radio button handling
|
|
document.querySelectorAll('.radio-option').forEach(option => {
|
|
option.addEventListener('click', function() {
|
|
document.querySelectorAll('.radio-option').forEach(opt => opt.classList.remove('selected'));
|
|
this.classList.add('selected');
|
|
this.querySelector('input[type="radio"]').checked = true;
|
|
});
|
|
});
|
|
|
|
// Analysis function
|
|
function analyzeData() {
|
|
if (!selectedFile) {
|
|
showToast('Please select a data file', 'error');
|
|
return;
|
|
}
|
|
|
|
// Check user authentication
|
|
{% if not user.is_authenticated %}
|
|
window.location.href = "{% url 'authentication:login' %}";
|
|
return;
|
|
{% endif %}
|
|
|
|
// Check wallet balance
|
|
const balance = {{ user.wallet_balance|default:0 }};
|
|
if (balance < 5.00) {
|
|
showToast('Insufficient balance! You need 5.00 AED.', 'error');
|
|
setTimeout(() => {
|
|
window.location.href = "{% url 'core:wallet' %}";
|
|
}, 2000);
|
|
return;
|
|
}
|
|
|
|
const analysisType = document.querySelector('input[name="analysisType"]:checked').value;
|
|
|
|
// Show processing status
|
|
document.getElementById('processingStatus').style.display = 'block';
|
|
document.getElementById('processButton').disabled = true;
|
|
document.getElementById('processButton').innerHTML = '⏳ Processing...';
|
|
document.getElementById('analysisResults').style.display = 'none';
|
|
|
|
// Processing steps for user feedback
|
|
const steps = [
|
|
'Reading file structure...',
|
|
'Extracting data patterns...',
|
|
'Performing statistical analysis...',
|
|
'Generating insights...',
|
|
'Finalizing report...'
|
|
];
|
|
|
|
let currentStep = 0;
|
|
const stepInterval = setInterval(() => {
|
|
if (currentStep < steps.length) {
|
|
document.getElementById('statusText').textContent = steps[currentStep];
|
|
currentStep++;
|
|
} else {
|
|
clearInterval(stepInterval);
|
|
}
|
|
}, 1000);
|
|
|
|
// Submit form data to backend
|
|
const formData = new FormData();
|
|
formData.append('file', selectedFile);
|
|
formData.append('analysis_type', analysisType);
|
|
formData.append('csrfmiddlewaretoken', document.querySelector('[name=csrfmiddlewaretoken]').value);
|
|
|
|
fetch('/agents/data-analyzer/process/', {
|
|
method: 'POST',
|
|
body: formData,
|
|
headers: {
|
|
'X-Requested-With': 'XMLHttpRequest'
|
|
}
|
|
})
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
clearInterval(stepInterval);
|
|
if (result.success && result.request_id) {
|
|
// Start polling for results
|
|
pollForResults(result.request_id);
|
|
} else {
|
|
// Handle immediate response
|
|
document.getElementById('processingStatus').style.display = 'none';
|
|
document.getElementById('processButton').disabled = false;
|
|
document.getElementById('processButton').innerHTML = '📊 Analyze Data (5.00 AED)';
|
|
|
|
if (result.error) {
|
|
showToast(`❌ ${result.error}`, 'error');
|
|
} else {
|
|
displayResults(result);
|
|
}
|
|
}
|
|
})
|
|
.catch(error => {
|
|
clearInterval(stepInterval);
|
|
console.error('Error:', error);
|
|
document.getElementById('processingStatus').style.display = 'none';
|
|
document.getElementById('processButton').disabled = false;
|
|
document.getElementById('processButton').innerHTML = '📊 Analyze Data (5.00 AED)';
|
|
showToast('❌ Network error - please try again', 'error');
|
|
});
|
|
}
|
|
|
|
// Display analysis results
|
|
function displayResults(result) {
|
|
const resultsContainer = document.getElementById('analysisResults');
|
|
const contentContainer = document.getElementById('analysisContent');
|
|
|
|
if (result.success && result.status === 'completed') {
|
|
// Use the analysis content from backend
|
|
const content = result.report_text || result.analysis_results || result.insights_summary || 'Data analysis completed successfully!';
|
|
contentContainer.textContent = content;
|
|
resultsContainer.style.display = 'block';
|
|
|
|
// Update wallet balance if provided
|
|
if (result.wallet_balance !== undefined) {
|
|
updateWalletBalance(result.wallet_balance);
|
|
}
|
|
|
|
showToast('✅ Data analysis completed and payment processed!', 'success');
|
|
} else {
|
|
showToast('❌ Failed to analyze data - no charge applied', 'error');
|
|
}
|
|
}
|
|
|
|
// Poll for results
|
|
function pollForResults(requestId) {
|
|
let pollCount = 0;
|
|
const maxPolls = 60; // 60 seconds maximum for data analysis
|
|
|
|
const pollInterval = setInterval(() => {
|
|
pollCount++;
|
|
|
|
fetch(`/agents/data-analyzer/result/${requestId}/`)
|
|
.then(response => response.json())
|
|
.then(result => {
|
|
if (result.status === 'completed' || result.status === 'failed') {
|
|
clearInterval(pollInterval);
|
|
document.getElementById('processingStatus').style.display = 'none';
|
|
document.getElementById('processButton').disabled = false;
|
|
document.getElementById('processButton').innerHTML = '📊 Analyze Data (5.00 AED)';
|
|
|
|
displayResults(result);
|
|
} else if (pollCount >= maxPolls) {
|
|
clearInterval(pollInterval);
|
|
document.getElementById('processingStatus').style.display = 'none';
|
|
document.getElementById('processButton').disabled = false;
|
|
document.getElementById('processButton').innerHTML = '📊 Analyze Data (5.00 AED)';
|
|
showToast('❌ Processing timeout - please try again', 'error');
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error polling results:', error);
|
|
if (pollCount >= maxPolls) {
|
|
clearInterval(pollInterval);
|
|
document.getElementById('processingStatus').style.display = 'none';
|
|
document.getElementById('processButton').disabled = false;
|
|
document.getElementById('processButton').innerHTML = '📊 Analyze Data (5.00 AED)';
|
|
showToast('❌ Network error - please try again', 'error');
|
|
}
|
|
});
|
|
}, 1000);
|
|
}
|
|
|
|
|
|
function updateWalletBalance(newBalance) {
|
|
// Update wallet balance display
|
|
const balanceElements = document.querySelectorAll('[data-wallet-balance]');
|
|
balanceElements.forEach(element => {
|
|
element.textContent = `${newBalance.toFixed(2)} AED`;
|
|
});
|
|
window.currentWalletBalance = newBalance;
|
|
}
|
|
|
|
function copyAnalysisReport() {
|
|
const reportText = document.getElementById('analysisContent').textContent;
|
|
navigator.clipboard.writeText(reportText).then(() => {
|
|
showToast('📋 Analysis report copied to clipboard!', 'success');
|
|
}).catch(() => {
|
|
showToast('Failed to copy report', 'error');
|
|
});
|
|
}
|
|
|
|
function downloadAnalysisReport() {
|
|
const reportText = document.getElementById('analysisContent').textContent;
|
|
const blob = new Blob([reportText], { type: 'text/plain' });
|
|
const url = URL.createObjectURL(blob);
|
|
const a = document.createElement('a');
|
|
a.href = url;
|
|
a.download = `data-analysis-report-${Date.now()}.txt`;
|
|
a.click();
|
|
URL.revokeObjectURL(url);
|
|
showToast('💾 Analysis report downloaded!', 'success');
|
|
}
|
|
|
|
function showToast(message, type = 'info') {
|
|
const toast = document.createElement('div');
|
|
toast.style.cssText = `
|
|
position: fixed;
|
|
top: 20px;
|
|
right: 20px;
|
|
padding: 12px 20px;
|
|
border-radius: 8px;
|
|
color: white;
|
|
font-weight: 600;
|
|
z-index: 1000;
|
|
${type === 'success' ? 'background: #10b981;' : 'background: #ef4444;'}
|
|
`;
|
|
toast.textContent = message;
|
|
document.body.appendChild(toast);
|
|
|
|
setTimeout(() => {
|
|
toast.remove();
|
|
}, 3000);
|
|
}
|
|
</script>
|
|
{% endblock %} |