Spaces:
Configuration error
Configuration error
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>iKnow | Snap & Know</title> | |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> | |
| <script src="https://cdn.tailwindcss.com"></script> | |
| <script src="https://unpkg.com/feather-icons"></script> | |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> | |
| <script> | |
| tailwind.config = { | |
| theme: { | |
| extend: { | |
| colors: { | |
| primary: '#5E72E4', | |
| secondary: '#FF9F43', | |
| }, | |
| fontSize: { | |
| 'xxl': '2.5rem', | |
| } | |
| } | |
| } | |
| } | |
| </script> | |
| <style> | |
| @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap'); | |
| @import url('https://fonts.googleapis.com/css2?family=Century+Gothic&display=swap'); | |
| body { | |
| font-family: 'Inter', sans-serif; | |
| } | |
| .text-shadow { | |
| text-shadow: 0 2px 4px rgba(0,0,0,0.1); | |
| } | |
| .btn-xxl { | |
| padding: 1.5rem 2rem; | |
| font-size: 1.5rem; | |
| } | |
| .speech-bubble { | |
| position: relative; | |
| background: white; | |
| border-radius: 1.5rem; | |
| } | |
| .speech-bubble:after { | |
| content: ''; | |
| position: absolute; | |
| bottom: -15px; | |
| left: 50%; | |
| width: 0; | |
| height: 0; | |
| border: 15px solid transparent; | |
| border-top-color: white; | |
| border-bottom: 0; | |
| margin-left: -15px; | |
| } | |
| </style> | |
| </head> | |
| <body class="bg-black"> | |
| <!-- Header --> | |
| <header class="fixed top-0 w-full bg-transparent py-6 px-4 z-10"> | |
| <div class="container mx-auto flex justify-between items-center"> | |
| <h1 class="text-white text-3xl font-normal" style="font-family: 'Century Gothic', sans-serif; letter-spacing: -1px; font-style: italic; text-shadow: 0 2px 4px rgba(0,0,0,0.2);">iKnow</h1> | |
| <div class="flex space-x-4"> | |
| <button class="p-3 rounded-full bg-white bg-opacity-20 text-white"> | |
| <i data-feather="settings"></i> | |
| </button> | |
| <button class="p-3 rounded-full bg-white bg-opacity-20 text-white"> | |
| <i data-feather="help-circle"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </header> | |
| <!-- Camera View --> | |
| <main class="fixed inset-0 bg-black"> | |
| <div class="relative w-full h-full"> | |
| <!-- Camera Preview --> | |
| <div class="absolute inset-0"> | |
| <!-- This would be replaced with actual camera feed --> | |
| <img src="http://static.photos/minimal/640x360/1" alt="Camera preview" class="w-full h-full object-cover"> | |
| </div> | |
| <!-- Camera Controls --> | |
| <div class="absolute bottom-0 left-0 right-0 pb-8 px-6 z-10"> | |
| <div class="flex justify-between items-center"> | |
| <!-- Flash toggle --> | |
| <button class="p-3 bg-white bg-opacity-20 rounded-full text-white"> | |
| <i data-feather="zap" class="w-6 h-6"></i> | |
| </button> | |
| <!-- Shutter button --> | |
| <button class="w-16 h-16 rounded-full border-4 border-white bg-white bg-opacity-30 flex items-center justify-center"> | |
| <div class="w-12 h-12 rounded-full bg-white"></div> | |
| </button> | |
| <!-- Flip camera --> | |
| <button class="p-3 bg-white bg-opacity-20 rounded-full text-white"> | |
| <i data-feather="refresh-cw" class="w-6 h-6"></i> | |
| </button> | |
| </div> | |
| <!-- Bottom buttons --> | |
| <div class="flex justify-center space-x-8 mt-6"> | |
| <button class="text-white opacity-70"> | |
| <i data-feather="image" class="w-6 h-6"></i> | |
| </button> | |
| <button class="text-white"> | |
| <i data-feather="aperture" class="w-8 h-8"></i> | |
| </button> | |
| <button class="text-white opacity-70"> | |
| <i data-feather="more-horizontal" class="w-6 h-6"></i> | |
| </button> | |
| </div> | |
| </div> | |
| </div> | |
| </main> | |
| <!-- Navigation --> | |
| <nav class="fixed bottom-0 w-full bg-transparent mx-auto max-w-md py-3 px-6 z-10"> | |
| <div class="flex justify-around"> | |
| <button class="flex flex-col items-center text-primary bg-transparent"> | |
| <i data-feather="home" class="w-6 h-6"></i> | |
| <span class="text-xs mt-1">Home</span> | |
| </button> | |
| <button class="flex flex-col items-center text-gray-400 bg-transparent"> | |
| <i data-feather="clock" class="w-6 h-6"></i> | |
| <span class="text-xs mt-1">History</span> | |
| </button> | |
| <button class="flex flex-col items-center text-gray-400 bg-transparent"> | |
| <i data-feather="heart" class="w-6 h-6"></i> | |
| <span class="text-xs mt-1">Favorites</span> | |
| </button> | |
| <button class="flex flex-col items-center text-gray-400 bg-transparent"> | |
| <i data-feather="user" class="w-6 h-6"></i> | |
| <span class="text-xs mt-1">Profile</span> | |
| </button> | |
| </div> | |
| </nav> | |
| <script> | |
| feather.replace(); | |
| // Mock API response for development | |
| if (window.location.hostname === 'localhost' || window.location.hostname === '127.0.0.1') { | |
| window.fetch = window.fetch || function(url, options) { | |
| if (url === '/api/analyze') { | |
| return Promise.resolve({ | |
| json: () => ({ | |
| description: "This appears to be a coffee mug on a wooden table. The mug is white with a simple design.", | |
| items: [ | |
| { label: "Coffee Mug", confidence: 0.92 }, | |
| { label: "Wooden Table", confidence: 0.87 } | |
| ] | |
| }) | |
| }); | |
| } | |
| return originalFetch(url, options); | |
| }; | |
| } | |
| // Camera shutter animation | |
| document.querySelector('[data-feather="aperture"]').closest('button').addEventListener('click', function() { | |
| const shutter = document.createElement('div'); | |
| shutter.className = 'absolute inset-0 bg-white opacity-0'; | |
| document.querySelector('.relative').appendChild(shutter); | |
| anime({ | |
| targets: shutter, | |
| opacity: [0, 1, 0], | |
| duration: 300, | |
| easing: 'easeInOutQuad', | |
| complete: () => shutter.remove() | |
| }); | |
| // Capture and process image | |
| const img = document.querySelector('.relative img'); | |
| const canvas = document.createElement('canvas'); | |
| canvas.width = img.width; | |
| canvas.height = img.height; | |
| const ctx = canvas.getContext('2d'); | |
| ctx.drawImage(img, 0, 0, canvas.width, canvas.height); | |
| const imageData = canvas.toDataURL('image/jpeg'); | |
| // Send to backend for processing | |
| fetch('/api/analyze', { | |
| method: 'POST', | |
| headers: { | |
| 'Content-Type': 'application/json', | |
| }, | |
| body: JSON.stringify({ image: imageData }) | |
| }) | |
| .then(response => response.json()) | |
| .then(data => { | |
| // Show results in a modal | |
| const resultsModal = document.createElement('div'); | |
| resultsModal.className = 'fixed inset-0 bg-black bg-opacity-80 z-50 flex items-center justify-center p-4'; | |
| resultsModal.innerHTML = ` | |
| <div class="bg-white rounded-xl p-6 max-w-md w-full"> | |
| <h3 class="text-xl font-bold mb-4">Results</h3> | |
| <p class="mb-4">${data.description}</p> | |
| <div class="grid gap-2 mb-4"> | |
| ${data.items.map(item => ` | |
| <div class="flex items-center"> | |
| <div class="w-3 h-3 rounded-full ${item.confidence > 0.7 ? 'bg-green-500' : 'bg-yellow-500'} mr-2"></div> | |
| <span>${item.label} (${Math.round(item.confidence * 100)}%)</span> | |
| </div> | |
| `).join('')} | |
| </div> | |
| <button onclick="this.closest('div').remove()" class="w-full bg-primary text-white py-2 rounded-lg"> | |
| Close | |
| </button> | |
| </div> | |
| `; | |
| document.body.appendChild(resultsModal); | |
| }) | |
| .catch(error => { | |
| console.error('Error:', error); | |
| alert('Failed to process image. Please try again.'); | |
| }); | |
| }); | |
| // Navigation handling | |
| document.querySelectorAll('nav button').forEach(button => { | |
| button.addEventListener('click', function() { | |
| document.querySelectorAll('nav button').forEach(btn => { | |
| btn.classList.remove('text-primary'); | |
| btn.classList.add('text-gray-400'); | |
| }); | |
| this.classList.remove('text-gray-400'); | |
| this.classList.add('text-primary'); | |
| }); | |
| }); | |
| // Flash toggle | |
| let flashOn = false; | |
| document.querySelector('[data-feather="zap"]').closest('button').addEventListener('click', function() { | |
| flashOn = !flashOn; | |
| const flashIcon = this.querySelector('i'); | |
| if (flashOn) { | |
| flashIcon.setAttribute('data-feather', 'zap-off'); | |
| this.classList.add('bg-opacity-80'); | |
| } else { | |
| flashIcon.setAttribute('data-feather', 'zap'); | |
| this.classList.remove('bg-opacity-80'); | |
| } | |
| feather.replace(); | |
| }); | |
| // Camera flip | |
| document.querySelector('[data-feather="refresh-cw"]').closest('button').addEventListener('click', function() { | |
| alert("Camera flipped!"); | |
| }); | |
| </script> | |
| </body> | |
| </html> | |