class SketchConverter { constructor() { this.initializeElements(); this.attachEventListeners(); this.currentFile = null; this.currentSketchUrl = null; } initializeElements() { this.uploadArea = document.getElementById('upload-area'); this.processingArea = document.getElementById('processing-area'); this.resultArea = document.getElementById('result-area'); this.settingsArea = document.getElementById('settings-area'); this.fileInput = document.getElementById('file-input'); this.browseBtn = document.getElementById('browse-btn'); this.originalImage = document.getElementById('original-image'); this.sketchImage = document.getElementById('sketch-image'); this.downloadBtn = document.getElementById('download-btn'); this.newUploadBtn = document.getElementById('new-upload-btn'); this.blurSelect = document.getElementById('blur-select'); this.enhanceCheck = document.getElementById('enhance-check'); } attachEventListeners() { // File input and browse button this.browseBtn.addEventListener('click', () => this.fileInput.click()); this.fileInput.addEventListener('change', (e) => this.handleFileSelect(e.target.files[0])); // Drag and drop this.uploadArea.addEventListener('dragover', (e) => this.handleDragOver(e)); this.uploadArea.addEventListener('dragleave', (e) => this.handleDragLeave(e)); this.uploadArea.addEventListener('drop', (e) => this.handleDrop(e)); // Result actions this.downloadBtn.addEventListener('click', () => this.downloadSketch()); this.newUploadBtn.addEventListener('click', () => this.resetInterface()); // Settings this.blurSelect.addEventListener('change', () => this.processCurrentFile()); this.enhanceCheck.addEventListener('change', () => this.processCurrentFile()); } handleDragOver(e) { e.preventDefault(); e.stopPropagation(); this.uploadArea.classList.add('border-primary'); } handleDragLeave(e) { e.preventDefault(); e.stopPropagation(); this.uploadArea.classList.remove('border-primary'); } handleDrop(e) { e.preventDefault(); e.stopPropagation(); this.uploadArea.classList.remove('border-primary'); const files = e.dataTransfer.files; if (files.length > 0) { this.handleFileSelect(files[0]); } } handleFileSelect(file) { if (!file) return; // Validate file type if (!file.type.startsWith('image/')) { this.showError('Please select a valid image file (JPG, PNG, etc.)'); return; } // Validate file size (max 10MB) if (file.size > 10 * 1024 * 1024) { this.showError('File size must be less than 10MB'); return; } this.currentFile = file; this.showOriginalImage(file); this.processCurrentFile(); } showOriginalImage(file) { const reader = new FileReader(); reader.onload = (e) => { this.originalImage.src = e.target.result; }; reader.readAsDataURL(file); } async processCurrentFile() { if (!this.currentFile) return; this.showProcessing(); const formData = new FormData(); formData.append('image', this.currentFile); formData.append('blur', this.blurSelect.value); formData.append('enhance', this.enhanceCheck.checked); try { const response = await fetch('/convert', { method: 'POST', body: formData }); if (!response.ok) { const errorData = await response.json(); throw new Error(errorData.error || 'Failed to process image'); } const result = await response.json(); this.showResult(result.sketch_url); } catch (error) { console.error('Error processing image:', error); this.showError(error.message || 'Failed to process image. Please try again.'); } } showProcessing() { this.hideAllAreas(); this.processingArea.classList.remove('hidden'); this.settingsArea.classList.remove('hidden'); } showResult(sketchUrl) { this.currentSketchUrl = sketchUrl; this.sketchImage.src = sketchUrl; this.hideAllAreas(); this.resultArea.classList.remove('hidden'); this.settingsArea.classList.remove('hidden'); } hideAllAreas() { this.uploadArea.classList.add('hidden'); this.processingArea.classList.add('hidden'); this.resultArea.classList.add('hidden'); this.settingsArea.classList.add('hidden'); } resetInterface() { this.currentFile = null; this.currentSketchUrl = null; this.fileInput.value = ''; this.hideAllAreas(); this.uploadArea.classList.remove('hidden'); // Reset settings to defaults this.blurSelect.value = '21'; this.enhanceCheck.checked = false; } downloadSketch() { if (!this.currentSketchUrl) return; const link = document.createElement('a'); link.href = this.currentSketchUrl; link.download = 'sketch.jpg'; document.body.appendChild(link); link.click(); document.body.removeChild(link); } showError(message) { // Create a simple toast notification const toast = document.createElement('div'); toast.className = 'fixed top-4 right-4 bg-red-500 text-white px-6 py-3 rounded-lg z-50'; toast.textContent = message; document.body.appendChild(toast); setTimeout(() => { document.body.removeChild(toast); }, 5000); this.resetInterface(); } } // Initialize the application when DOM is loaded document.addEventListener('DOMContentLoaded', () => { new SketchConverter(); });