| class ClothingAnalyzer { |
| constructor() { |
| this.imageInput = document.getElementById('imageInput'); |
| this.uploadArea = document.getElementById('uploadArea'); |
| this.analyzeBtn = document.getElementById('analyzeBtn'); |
| this.previewSection = document.getElementById('previewSection'); |
| this.imagePreview = document.getElementById('imagePreview'); |
| this.loading = document.getElementById('loading'); |
| this.results = document.getElementById('results'); |
| |
| this.initializeEventListeners(); |
| } |
| |
| initializeEventListeners() { |
| |
| this.uploadArea.addEventListener('click', () => { |
| this.imageInput.click(); |
| }); |
| |
| |
| this.imageInput.addEventListener('change', (e) => { |
| this.handleFileSelect(e.target.files[0]); |
| }); |
| |
| |
| this.uploadArea.addEventListener('dragover', (e) => { |
| e.preventDefault(); |
| this.uploadArea.classList.add('dragover'); |
| }); |
| |
| this.uploadArea.addEventListener('dragleave', () => { |
| this.uploadArea.classList.remove('dragover'); |
| }); |
| |
| this.uploadArea.addEventListener('drop', (e) => { |
| e.preventDefault(); |
| this.uploadArea.classList.remove('dragover'); |
| this.handleFileSelect(e.dataTransfer.files[0]); |
| }); |
| |
| |
| this.analyzeBtn.addEventListener('click', () => { |
| this.analyzeImage(); |
| }); |
| } |
| |
| handleFileSelect(file) { |
| if (!file) return; |
| |
| |
| if (!file.type.startsWith('image/')) { |
| alert('Please select a valid image file'); |
| return; |
| } |
| |
| |
| const reader = new FileReader(); |
| reader.onload = (e) => { |
| this.imagePreview.src = e.target.result; |
| this.previewSection.style.display = 'block'; |
| this.analyzeBtn.disabled = false; |
| this.results.style.display = 'none'; |
| }; |
| reader.readAsDataURL(file); |
| |
| |
| this.selectedFile = file; |
| } |
| |
| async analyzeImage() { |
| if (!this.selectedFile) return; |
| |
| |
| this.loading.style.display = 'block'; |
| this.results.style.display = 'none'; |
| this.analyzeBtn.disabled = true; |
| |
| try { |
| |
| const formData = new FormData(); |
| formData.append('file', this.selectedFile); |
| |
| |
| const response = await fetch('/analyze', { |
| method: 'POST', |
| body: formData |
| }); |
| |
| if (!response.ok) { |
| throw new Error(`HTTP error! status: ${response.status}`); |
| } |
| |
| const data = await response.json(); |
| this.displayResults(data); |
| |
| } catch (error) { |
| console.error('Analysis failed:', error); |
| alert('Analysis failed. Please try again.'); |
| } finally { |
| this.loading.style.display = 'none'; |
| this.analyzeBtn.disabled = false; |
| } |
| } |
| |
| displayResults(data) { |
| |
| document.getElementById('styleResult').textContent = data.style_classification; |
| document.getElementById('formalityResult').textContent = data.formality; |
| document.getElementById('textureResult').textContent = data.texture; |
| |
| |
| const itemsHtml = data.clothing_items |
| .map(item => `<div class="item-tag">${item.item_type} (${Math.round(item.confidence * 100)}%)</div>`) |
| .join(''); |
| document.getElementById('itemsResult').innerHTML = itemsHtml || 'No items detected'; |
| |
| |
| this.displayColorPalette(data.dominant_colors); |
| |
| |
| this.displayConfidenceScores(data.confidence_scores); |
| |
| |
| this.results.style.display = 'block'; |
| } |
| |
| displayColorPalette(colors) { |
| const colorPalette = document.getElementById('colorPalette'); |
| |
| const colorHtml = colors.map(color => ` |
| <div class="color-item"> |
| <div class="color-swatch" style="background-color: ${color.hex}"></div> |
| <div> |
| <div style="font-weight: 600">${color.color_name}</div> |
| <div style="font-size: 0.9rem; color: #64748b">${color.percentage}%</div> |
| </div> |
| </div> |
| `).join(''); |
| |
| colorPalette.innerHTML = colorHtml; |
| } |
| |
| displayConfidenceScores(scores) { |
| const confidenceContainer = document.getElementById('confidenceScores'); |
| |
| const scoresHtml = Object.entries(scores).map(([key, value]) => ` |
| <div style="margin-bottom: 15px"> |
| <div style="display: flex; justify-content: space-between; margin-bottom: 5px"> |
| <span style="text-transform: capitalize">${key}</span> |
| <span>${Math.round(value * 100)}%</span> |
| </div> |
| <div class="confidence-bar"> |
| <div class="confidence-fill" style="width: ${value * 100}%"></div> |
| </div> |
| </div> |
| `).join(''); |
| |
| confidenceContainer.innerHTML = scoresHtml; |
| } |
| } |
|
|
| |
| document.addEventListener('DOMContentLoaded', () => { |
| new ClothingAnalyzer(); |
| }); |
|
|