// API Configuration const API_BASE_URL = window.location.origin; // DOM Elements const uploadArea = document.getElementById('uploadArea'); const imageInput = document.getElementById('imageInput'); const imagePreview = document.getElementById('imagePreview'); const previewImg = document.getElementById('previewImg'); const analyzeBtn = document.getElementById('analyzeBtn'); const loading = document.getElementById('loading'); const resultsSection = document.getElementById('resultsSection'); // Preference selectors const aestheticSelect = document.getElementById('aesthetic'); const nicheSelect = document.getElementById('niche'); const targetAudienceSelect = document.getElementById('targetAudience'); const contentTypeSelect = document.getElementById('contentType'); const brandVoiceSelect = document.getElementById('brandVoice'); // State let selectedImage = null; let preferences = null; let enhancedImages = []; let currentEnhancementIndex = 0; // Initialize the application document.addEventListener('DOMContentLoaded', function() { loadPreferences(); setupEventListeners(); }); // Load available preferences from API async function loadPreferences() { try { const response = await fetch(`${API_BASE_URL}/available-preferences`); if (response.ok) { const data = await response.json(); populateSelects(data); } else { showError('Failed to load preferences. Make sure the API server is running.'); } } catch (error) { console.error('Error loading preferences:', error); showError('Failed to connect to API server. Please start the server with: python api.py'); } } // Populate preference dropdowns function populateSelects(data) { // Populate aesthetics data.aesthetics.forEach(aesthetic => { const option = document.createElement('option'); option.value = aesthetic; option.textContent = aesthetic; aestheticSelect.appendChild(option); }); // Populate niches data.niches.forEach(niche => { const option = document.createElement('option'); option.value = niche; option.textContent = niche; nicheSelect.appendChild(option); }); // Populate target audiences data.target_audiences.forEach(audience => { const option = document.createElement('option'); option.value = audience; option.textContent = audience; targetAudienceSelect.appendChild(option); }); // Populate content types data.content_types.forEach(type => { const option = document.createElement('option'); option.value = type; option.textContent = type; contentTypeSelect.appendChild(option); }); // Populate brand voices data.brand_voices.forEach(voice => { const option = document.createElement('option'); option.value = voice; option.textContent = voice; brandVoiceSelect.appendChild(option); }); } // Setup event listeners function setupEventListeners() { // Upload area click uploadArea.addEventListener('click', () => { imageInput.click(); }); // File input change imageInput.addEventListener('change', handleImageSelect); // Drag and drop uploadArea.addEventListener('dragover', handleDragOver); uploadArea.addEventListener('dragleave', handleDragLeave); uploadArea.addEventListener('drop', handleDrop); // Analyze button analyzeBtn.addEventListener('click', analyzeImage); // Preference changes aestheticSelect.addEventListener('change', updateAnalyzeButton); nicheSelect.addEventListener('change', updateAnalyzeButton); targetAudienceSelect.addEventListener('change', updateAnalyzeButton); contentTypeSelect.addEventListener('change', updateAnalyzeButton); brandVoiceSelect.addEventListener('change', updateAnalyzeButton); } // Handle image selection function handleImageSelect(event) { const file = event.target.files[0]; if (file) { processImageFile(file); } } // Handle drag over function handleDragOver(event) { event.preventDefault(); uploadArea.classList.add('dragover'); } // Handle drag leave function handleDragLeave(event) { event.preventDefault(); uploadArea.classList.remove('dragover'); } // Handle drop function handleDrop(event) { event.preventDefault(); uploadArea.classList.remove('dragover'); const files = event.dataTransfer.files; if (files.length > 0) { processImageFile(files[0]); } } // Process image file function processImageFile(file) { // Validate file type if (!file.type.startsWith('image/')) { showError('Please select a valid image file.'); return; } // Validate file size (10MB limit) if (file.size > 10 * 1024 * 1024) { showError('Image file size must be less than 10MB.'); return; } // Create preview const reader = new FileReader(); reader.onload = function(e) { previewImg.src = e.target.result; imagePreview.style.display = 'block'; selectedImage = file; updateAnalyzeButton(); }; reader.readAsDataURL(file); } // Update analyze button state function updateAnalyzeButton() { const hasImage = selectedImage !== null; const hasPreferences = aestheticSelect.value || nicheSelect.value || targetAudienceSelect.value || contentTypeSelect.value || brandVoiceSelect.value; analyzeBtn.disabled = !hasImage; if (hasImage && hasPreferences) { analyzeBtn.innerHTML = ' Analyze with Preferences'; } else if (hasImage) { analyzeBtn.innerHTML = ' Analyze Image'; } } // Analyze image async function analyzeImage() { if (!selectedImage) { showError('Please select an image first.'); return; } // Show loading loading.style.display = 'block'; resultsSection.style.display = 'none'; analyzeBtn.disabled = true; try { // Convert image to base64 const base64Image = await fileToBase64(selectedImage); // Prepare request data const requestData = { image: base64Image }; // Add preferences if any are selected const userPreferences = {}; if (aestheticSelect.value) userPreferences.aesthetic = aestheticSelect.value; if (nicheSelect.value) userPreferences.niche = nicheSelect.value; if (targetAudienceSelect.value) userPreferences.target_audience = targetAudienceSelect.value; if (contentTypeSelect.value) userPreferences.content_type = contentTypeSelect.value; if (brandVoiceSelect.value) userPreferences.brand_voice = brandVoiceSelect.value; if (Object.keys(userPreferences).length > 0) { requestData.user_preferences = userPreferences; } // Send request to API const response = await fetch(`${API_BASE_URL}/score-image`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestData) }); if (response.ok) { const result = await response.json(); displayResults(result); } else { const errorData = await response.json(); throw new Error(errorData.detail || 'Analysis failed'); } } catch (error) { console.error('Analysis error:', error); showError(`Analysis failed: ${error.message}`); } finally { // Hide loading loading.style.display = 'none'; analyzeBtn.disabled = false; } } // Convert file to base64 function fileToBase64(file) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.readAsDataURL(file); reader.onload = () => { // Remove the data URL prefix (e.g., "data:image/jpeg;base64,") const base64 = reader.result.split(',')[1]; resolve(base64); }; reader.onerror = error => reject(error); }); } // Display results function displayResults(result) { // Check if content was rejected if (result.status === 'rejected') { displayRejectedContent(result); return; } // Update final score document.getElementById('finalScore').textContent = result.final_score; // Update score breakdown const scoreBreakdown = document.getElementById('scoreBreakdown'); scoreBreakdown.innerHTML = ''; const scoreCategories = [ { key: 'technical_quality', name: 'Technical Quality', icon: '🔧' }, { key: 'compositional_strength', name: 'Compositional Strength', icon: '📐' }, { key: 'psychological_engagement', name: 'Psychological Engagement', icon: '🧠' }, { key: 'trend_zeitgeist', name: 'Trend & Zeitgeist', icon: '📈' } ]; scoreCategories.forEach(category => { const scoreData = result[category.key]; const card = document.createElement('div'); card.className = 'score-card'; card.innerHTML = `

${category.icon} ${category.name}

${scoreData.score}/100
${scoreData.details}
`; scoreBreakdown.appendChild(card); }); // Update recommendations const recommendationList = document.getElementById('recommendationList'); recommendationList.innerHTML = ''; if (result.recommendations && result.recommendations.length > 0) { result.recommendations.forEach(recommendation => { const li = document.createElement('li'); li.textContent = recommendation; recommendationList.appendChild(li); }); } else { const li = document.createElement('li'); li.textContent = 'No specific recommendations available.'; recommendationList.appendChild(li); } // Show results resultsSection.style.display = 'block'; // Add enhancement button if score is low if (result.final_score < 80) { addEnhancementButton(); } // Scroll to results resultsSection.scrollIntoView({ behavior: 'smooth' }); } // Display rejected content message function displayRejectedContent(result) { // Update final score to show 0 document.getElementById('finalScore').textContent = '0'; document.getElementById('finalScore').style.color = '#e74c3c'; // Clear score breakdown const scoreBreakdown = document.getElementById('scoreBreakdown'); scoreBreakdown.innerHTML = ''; // Create rejection message card const rejectionCard = document.createElement('div'); rejectionCard.className = 'score-card rejection-card'; rejectionCard.innerHTML = `

🚫 Content Rejected

${result.message}

Reason: ${result.rejection_reason}

`; scoreBreakdown.appendChild(rejectionCard); // Add risk analysis card if moderation details are available if (result.moderation_details && result.moderation_details.risk_scores) { const riskCard = document.createElement('div'); riskCard.className = 'score-card risk-analysis-card'; const riskScores = result.moderation_details.risk_scores; const violations = result.moderation_details.violations || []; let riskContent = '

🔍 Risk Analysis

'; riskContent += '
'; // Display risk scores const riskCategories = [ { key: 'adult', name: 'Adult Content', icon: '🔞' }, { key: 'violence', name: 'Violence', icon: '⚔️' }, { key: 'racy', name: 'Racy Content', icon: '💋' }, { key: 'medical', name: 'Medical Content', icon: '🏥' }, { key: 'spoof', name: 'Spoof/Manipulated', icon: '🎭' } ]; riskCategories.forEach(category => { const score = riskScores[category.key] || 0; const riskLevel = getRiskLevelText(score); const riskClass = getRiskClass(score); riskContent += `
${category.icon} ${category.name} ${score}/5 ${riskLevel}
`; }); riskContent += '
'; // Display violations if any if (violations.length > 0) { riskContent += '
'; riskContent += '
🚨 Detected Violations:
'; riskContent += ''; riskContent += '
'; } riskCard.innerHTML = riskContent; scoreBreakdown.appendChild(riskCard); } // Update recommendations with content guidelines const recommendationList = document.getElementById('recommendationList'); recommendationList.innerHTML = ''; if (result.recommendations && result.recommendations.length > 0) { result.recommendations.forEach(recommendation => { const li = document.createElement('li'); li.textContent = recommendation; recommendationList.appendChild(li); }); } // Show results resultsSection.style.display = 'block'; // Scroll to results resultsSection.scrollIntoView({ behavior: 'smooth' }); } // Helper function to get risk level text function getRiskLevelText(score) { switch(score) { case 0: return 'Unknown'; case 1: return 'Very Unlikely'; case 2: return 'Unlikely'; case 3: return 'Possible'; case 4: return 'Likely'; case 5: return 'Very Likely'; default: return 'Unknown'; } } // Helper function to get risk class for styling function getRiskClass(score) { if (score >= 4) return 'high-risk'; if (score >= 3) return 'medium-risk'; return 'low-risk'; } // Add enhancement button to results function addEnhancementButton() { const resultsSection = document.getElementById('resultsSection'); // Remove existing enhancement button const existingButton = document.getElementById('enhancementBtn'); if (existingButton) { existingButton.remove(); } // Create enhancement button const enhancementBtn = document.createElement('button'); enhancementBtn.id = 'enhancementBtn'; enhancementBtn.className = 'enhancement-btn'; enhancementBtn.innerHTML = ' Enhance Image with AI'; enhancementBtn.onclick = enhanceImage; // Insert after score display const scoreDisplay = document.querySelector('.score-display'); scoreDisplay.parentNode.insertBefore(enhancementBtn, scoreDisplay.nextSibling); } // Enhance image with AI async function enhanceImage() { if (!selectedImage) { showError('Please select an image first.'); return; } // Show loading const loading = document.getElementById('loading'); loading.style.display = 'block'; loading.querySelector('p').textContent = 'Generating enhanced images with AI...'; const enhancementBtn = document.getElementById('enhancementBtn'); if (enhancementBtn) { enhancementBtn.disabled = true; } try { // Convert image to base64 const base64Image = await fileToBase64(selectedImage); // Prepare request data const requestData = { image: base64Image }; // Add preferences if any are selected const userPreferences = {}; if (aestheticSelect.value) userPreferences.aesthetic = aestheticSelect.value; if (nicheSelect.value) userPreferences.niche = nicheSelect.value; if (targetAudienceSelect.value) userPreferences.target_audience = targetAudienceSelect.value; if (contentTypeSelect.value) userPreferences.content_type = contentTypeSelect.value; if (brandVoiceSelect.value) userPreferences.brand_voice = brandVoiceSelect.value; if (Object.keys(userPreferences).length > 0) { requestData.user_preferences = userPreferences; } // Send enhancement request const response = await fetch(`${API_BASE_URL}/enhance-image`, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(requestData) }); if (response.ok) { const result = await response.json(); enhancedImages = result.enhanced_images; currentEnhancementIndex = 0; if (enhancedImages.length > 0) { displayEnhancedImages(); } else { showError('No enhanced images were generated.'); } } else { const errorData = await response.json(); throw new Error(errorData.detail || 'Enhancement failed'); } } catch (error) { console.error('Enhancement error:', error); showError(`Enhancement failed: ${error.message}`); } finally { // Hide loading loading.style.display = 'none'; loading.querySelector('p').textContent = 'Analyzing your image with AI...'; if (enhancementBtn) { enhancementBtn.disabled = false; } } } // Display enhanced images function displayEnhancedImages() { const resultsSection = document.getElementById('resultsSection'); // Remove existing enhancement section const existingEnhancement = document.getElementById('enhancementSection'); if (existingEnhancement) { existingEnhancement.remove(); } // Create enhancement section const enhancementSection = document.createElement('div'); enhancementSection.id = 'enhancementSection'; enhancementSection.className = 'enhancement-section'; enhancementSection.innerHTML = `

AI Enhanced Images

${currentEnhancementIndex + 1} / ${enhancedImages.length}

Original

Original

Enhanced Version ${currentEnhancementIndex + 1}

Enhanced
Enhancement Details:

${enhancedImages[currentEnhancementIndex].prompt}

`; resultsSection.appendChild(enhancementSection); enhancementSection.scrollIntoView({ behavior: 'smooth' }); updateEnhancementControls(); } // Navigation functions for enhanced images window.previousEnhancedImage = function() { if (currentEnhancementIndex > 0) { currentEnhancementIndex--; displayEnhancedImages(); } }; window.nextEnhancedImage = function() { if (currentEnhancementIndex < enhancedImages.length - 1) { currentEnhancementIndex++; displayEnhancedImages(); } }; window.rejectEnhancedImage = function() { // Remove current enhanced image from array enhancedImages.splice(currentEnhancementIndex, 1); if (enhancedImages.length === 0) { // No more enhanced images const enhancementSection = document.getElementById('enhancementSection'); if (enhancementSection) { enhancementSection.remove(); } showSuccess('All enhanced images have been discarded.'); } else { // Adjust index if needed if (currentEnhancementIndex >= enhancedImages.length) { currentEnhancementIndex = enhancedImages.length - 1; } displayEnhancedImages(); } }; window.saveEnhancedImage = function() { const enhancedImage = enhancedImages[currentEnhancementIndex]; // Create download link const link = document.createElement('a'); link.href = `data:image/jpeg;base64,${enhancedImage.image}`; link.download = `enhanced_image_v${enhancedImage.version}.jpg`; link.click(); showSuccess(`Enhanced image version ${enhancedImage.version} saved successfully!`); }; // Update enhancement navigation controls function updateEnhancementControls() { const prevBtn = document.getElementById('prevBtn'); const nextBtn = document.getElementById('nextBtn'); const counter = document.querySelector('.enhancement-counter'); if (prevBtn) prevBtn.disabled = currentEnhancementIndex === 0; if (nextBtn) nextBtn.disabled = currentEnhancementIndex === enhancedImages.length - 1; if (counter) counter.textContent = `${currentEnhancementIndex + 1} / ${enhancedImages.length}`; } // Show error message function showError(message) { // Remove existing error messages const existingError = document.querySelector('.error'); if (existingError) { existingError.remove(); } // Create error element const errorDiv = document.createElement('div'); errorDiv.className = 'error'; errorDiv.innerHTML = ` ${message}`; // Insert after header const mainContent = document.querySelector('.main-content'); mainContent.insertBefore(errorDiv, mainContent.firstChild); // Auto-remove after 5 seconds setTimeout(() => { if (errorDiv.parentNode) { errorDiv.remove(); } }, 5000); } // Show success message function showSuccess(message) { // Remove existing success messages const existingSuccess = document.querySelector('.success'); if (existingSuccess) { existingSuccess.remove(); } // Create success element const successDiv = document.createElement('div'); successDiv.className = 'success'; successDiv.innerHTML = ` ${message}`; // Insert after header const mainContent = document.querySelector('.main-content'); mainContent.insertBefore(successDiv, mainContent.firstChild); // Auto-remove after 3 seconds setTimeout(() => { if (successDiv.parentNode) { successDiv.remove(); } }, 3000); }