document.addEventListener('DOMContentLoaded', () => { const dropZone = document.getElementById('drop-zone'); const fileInput = document.getElementById('file-input'); const previewContainer = document.getElementById('preview-container'); const imagePreview = document.getElementById('image-preview'); const removeBtn = document.getElementById('remove-btn'); const analyzeBtn = document.getElementById('analyze-btn'); const resultContainer = document.getElementById('result-container'); const resultBadge = document.getElementById('result-badge'); const tabDetector = document.getElementById('tab-detector'); const tabRisk = document.getElementById('tab-risk'); let currentMode = 'detector'; // 'detector' or 'risk' const modelLabel = document.getElementById('model-label'); const btnText = analyzeBtn.querySelector('.btn-text'); const loader = analyzeBtn.querySelector('.loader'); let currentFile = null; // --- Tab Switching --- function switchTab(mode) { currentMode = mode; resultContainer.classList.add('hidden'); // Hide previous results if (mode === 'detector') { tabDetector.className = 'px-6 py-2 rounded-full font-medium transition-all duration-300 bg-white text-black shadow-[0_0_20px_-5px_rgba(255,255,255,0.5)]'; tabRisk.className = 'px-6 py-2 rounded-full font-medium transition-all duration-300 bg-white/5 text-brand-gray hover:bg-white/10 hover:text-white border border-white/10'; btnText.textContent = 'Analyze Authenticity'; } else { tabRisk.className = 'px-6 py-2 rounded-full font-medium transition-all duration-300 bg-brand-green text-black shadow-[0_0_20px_-5px_rgba(0,220,130,0.5)]'; tabDetector.className = 'px-6 py-2 rounded-full font-medium transition-all duration-300 bg-white/5 text-brand-gray hover:bg-white/10 hover:text-white border border-white/10'; btnText.textContent = 'Check Identity Risk'; } } tabDetector.addEventListener('click', () => switchTab('detector')); tabRisk.addEventListener('click', () => switchTab('risk')); // --- Drag & Drop --- dropZone.addEventListener('click', () => fileInput.click()); dropZone.addEventListener('dragover', (e) => { e.preventDefault(); dropZone.classList.add('dragover'); }); dropZone.addEventListener('dragleave', () => { dropZone.classList.remove('dragover'); }); dropZone.addEventListener('drop', (e) => { e.preventDefault(); dropZone.classList.remove('dragover'); if (e.dataTransfer.files.length) { handleFile(e.dataTransfer.files[0]); } }); fileInput.addEventListener('change', (e) => { if (e.target.files.length) { handleFile(e.target.files[0]); } }); // --- File Handling --- function handleFile(file) { if (!file.type.startsWith('image/')) { alert('Please upload an image file (JPG, PNG).'); return; } currentFile = file; const reader = new FileReader(); reader.onload = (e) => { imagePreview.src = e.target.result; dropZone.classList.add('hidden'); previewContainer.classList.remove('hidden'); analyzeBtn.disabled = false; resultContainer.classList.add('hidden'); }; reader.readAsDataURL(file); } // --- Reset --- removeBtn.addEventListener('click', () => { currentFile = null; fileInput.value = ''; dropZone.classList.remove('hidden'); previewContainer.classList.add('hidden'); analyzeBtn.disabled = true; resultContainer.classList.add('hidden'); }); // --- Prediction --- analyzeBtn.addEventListener('click', async () => { if (!currentFile) return; // UI Loading State analyzeBtn.disabled = true; btnText.textContent = currentMode === 'detector' ? 'Analysing...' : 'Checking Risk...'; loader.classList.remove('hidden'); resultContainer.classList.add('hidden'); const formData = new FormData(); formData.append('image', currentFile); try { const response = await fetch('/predict', { method: 'POST', body: formData }); if (!response.ok) throw new Error('API Error'); const data = await response.json(); displayResult(data); } catch (error) { console.error(error); alert('Error processing image. Please try again.'); } finally { // UI Reset State analyzeBtn.disabled = false; btnText.textContent = currentMode === 'detector' ? 'Analyze Authenticity' : 'Check Identity Risk'; loader.classList.add('hidden'); } }); function displayResult(data) { resultContainer.classList.remove('hidden'); const badgeContainer = document.getElementById('result-badge-container'); // Remove existing detailed warnings/lists const existingWarning = document.getElementById('risk-warning'); if (existingWarning) existingWarning.remove(); const existingList = document.getElementById('risk-details'); if (existingList) existingList.remove(); const confidenceWrapper = document.getElementById('confidence-wrapper'); const explanationsSection = document.getElementById('explanations-section'); const qualificationTag = document.getElementById('qualification-tag'); // [NEW] if (currentMode === 'detector') { // --- AI Detector Mode --- if (confidenceWrapper) confidenceWrapper.classList.remove('hidden'); // Show in Detector Mode modelLabel.textContent = 'AI Detection Result'; const label = data.prediction.toLowerCase(); resultBadge.textContent = label.toUpperCase(); // [NEW] Qualification Tag Logic if (qualificationTag) { if (data.classification_tag) { qualificationTag.classList.remove('hidden'); qualificationTag.textContent = data.classification_tag; // Dynamic Styling based on content qualificationTag.className = "px-3 py-1 rounded-full text-[10px] font-bold uppercase tracking-wider border transition-colors duration-300"; if (data.classification_tag.includes("AI") || data.classification_tag.includes("Manipulation")) { qualificationTag.classList.add("bg-red-500/10", "border-red-500/20", "text-red-200"); } else if (data.classification_tag.includes("Raw")) { qualificationTag.classList.add("bg-brand-green/10", "border-brand-green/20", "text-brand-green"); } else { qualificationTag.classList.add("bg-yellow-500/10", "border-yellow-500/20", "text-yellow-200"); } } else { qualificationTag.classList.add('hidden'); } } // Confidence Update const confidenceBar = document.getElementById('confidence-bar'); const confidenceValue = document.getElementById('confidence-value'); const percent = Math.round(data.confidence * 100); // Animate Bar setTimeout(() => { confidenceBar.style.width = `${percent}%`; }, 100); confidenceValue.textContent = `${percent}%`; resultBadge.className = 'text-3xl font-bold tracking-tight transition-colors duration-300'; confidenceBar.className = 'h-full w-0 rounded-full transition-all duration-1000 ease-out'; // Reset base if (label.includes('real')) { resultBadge.classList.add('text-brand-green', 'drop-shadow-[0_0_15px_rgba(0,220,130,0.5)]'); confidenceBar.classList.add('bg-brand-green', 'shadow-[0_0_10px_rgba(0,220,130,0.5)]'); } else if (label.includes('fake') || label.includes('ai')) { resultBadge.classList.add('text-red-500', 'drop-shadow-[0_0_15px_rgba(255,50,50,0.5)]'); confidenceBar.classList.add('bg-red-500', 'shadow-[0_0_10px_rgba(255,50,50,0.5)]'); } else { resultBadge.classList.add('text-brand-gray'); confidenceBar.classList.add('bg-gray-500'); } // [NEW] Analysis Points Logic const explanationsSection = document.getElementById('explanations-section'); const reasonsList = document.getElementById('reasons-list'); reasonsList.innerHTML = ''; // Clear previous if (data.analysis_points && data.analysis_points.length > 0) { explanationsSection.classList.remove('hidden'); data.analysis_points.forEach(point => { const li = document.createElement('li'); li.className = 'text-gray-300 text-sm flex items-start gap-2.5 leading-relaxed'; li.innerHTML = ` ${point} `; // Change icon for AI points if (label.includes('ai')) { li.innerHTML = ` ${point} `; } reasonsList.appendChild(li); }); } else { explanationsSection.classList.add('hidden'); } // Old Warning for "Real" images in Detection Mode (optional, keeping minimal as per request) if (data.risk_analysis && data.risk_analysis.is_high_risk && label.includes('real')) { const warningDiv = document.createElement('div'); warningDiv.id = 'risk-warning'; warningDiv.className = 'mt-4 p-3 rounded-xl bg-orange-500/10 border border-orange-500/20 backdrop-blur-sm animate-fade-in-up'; warningDiv.innerHTML = `
Identity Risk Detected. Switch to the Identity Risk tab for details.