| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>Aquaculture Biosecurity Ops</title> |
| <link rel="icon" type="image/x-icon" href="/static/favicon.ico"> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet"> |
| <script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script> |
| <script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script> |
| <script src="https://unpkg.com/feather-icons"></script> |
| <style> |
| .offline-banner { |
| background: linear-gradient(90deg, #f59e0b, #d97706); |
| } |
| .sync-queue { |
| background: linear-gradient(90deg, #3b82f6, #1d4ed8); |
| } |
| .alert-badge { |
| background: linear-gradient(90deg, #ef4444, #dc2626); |
| } |
| .treatment-card { |
| background: linear-gradient(90deg, #10b981, #059669); |
| } |
| .big-tap-button { |
| min-height: 60px; |
| min-width: 60px; |
| } |
| .stage-counter { |
| transition: all 0.2s ease; |
| } |
| .stage-counter:active { |
| transform: scale(0.95); |
| } |
| </style> |
| </head> |
| <body class="bg-blue-50 min-h-screen font-sans"> |
| |
| <div class="offline-banner text-white py-2 px-4 text-center hidden" id="offlineBanner"> |
| <div class="flex items-center justify-center"> |
| <i data-feather="wifi-off" class="mr-2"></i> |
| <span>Working offline - Data will sync when connection is restored</span> |
| </div> |
| </div> |
|
|
| |
| <nav class="bg-white shadow-lg fixed bottom-0 w-full z-50 md:relative md:top-0"> |
| <div class="flex justify-around items-center py-3 md:py-4"> |
| <a href="#sites" class="flex flex-col items-center text-blue-600"> |
| <i data-feather="map-pin" class="w-6 h-6 md:w-7 md:h-7"></i> |
| <span class="text-xs mt-1">Sites</span> |
| </a> |
| <a href="#planner" class="flex flex-col items-center text-gray-600"> |
| <i data-feather="calendar" class="w-6 h-6 md:w-7 md:h-7"></i> |
| <span class="text-xs mt-1">Planner</span> |
| </a> |
| <a href="#reports" class="flex flex-col items-center text-gray-600"> |
| <i data-feather="file-text" class="w-6 h-6 md:w-7 md:h-7"></i> |
| <span class="text-xs mt-1">Reports</span> |
| </a> |
| <a href="#maps" class="flex flex-col items-center text-gray-600"> |
| <i data-feather="map" class="w-6 h-6 md:w-7 md:h-7"></i> |
| <span class="text-xs mt-1">Maps</span> |
| </a> |
| <a href="#sync" class="flex flex-col items-center text-gray-600 relative"> |
| <i data-feather="refresh-cw" class="w-6 h-6 md:w-7 md:h-7"></i> |
| <span class="text-xs mt-1">Sync</span> |
| <span class="absolute -top-1 -right-1 bg-red-500 text-white rounded-full text-xs w-4 h-4 flex items-center justify-center hidden" id="syncCount">0</span> |
| </a> |
| </div> |
| </nav> |
|
|
| |
| <main class="pb-20 md:pb-0 md:pt-20"> |
| |
| <section id="sites" class="p-4" data-aos="fade-up"> |
| <h2 class="text-2xl font-bold text-gray-800 mb-4">Your Sites</h2> |
| |
| <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> |
| |
| <div class="bg-white rounded-xl shadow-md p-4"> |
| <div class="flex justify-between items-start"> |
| <h3 class="font-semibold text-lg">North Fjord Site</h3> |
| <span class="bg-green-100 text-green-800 text-xs px-2 py-1 rounded-full">Active</span> |
| </div> |
| <p class="text-gray-600 text-sm mt-2">12 pens • 4500 tons biomass</p> |
| |
| <div class="mt-4 space-y-2"> |
| <div class="flex justify-between items-center"> |
| <span class="text-sm">Last lice check:</span> |
| <span class="font-medium">2 hours ago</span> |
| </div> |
| <div class="flex justify-between items-center"> |
| <span class="text-sm">Avg lice count:</span> |
| <span class="font-medium text-orange-600">3.2</span> |
| </div> |
| </div> |
| |
| <button class="w-full bg-blue-600 text-white py-3 rounded-lg mt-4 font-medium flex items-center justify-center"> |
| <i data-feather="arrow-right" class="mr-2 w-4 h-4"></i> |
| View Pens |
| </button> |
| </div> |
| |
| |
| </div> |
| </section> |
|
|
| |
| <section class="p-4 bg-white mt-6" data-aos="fade-up"> |
| <h2 class="text-xl font-bold text-gray-800 mb-4">Quick Actions</h2> |
| <div class="grid grid-cols-2 gap-3"> |
| <button class="bg-blue-100 text-blue-800 py-4 rounded-lg font-medium flex flex-col items-center justify-center"> |
| <i data-feather="plus-circle" class="w-8 h-8 mb-2"></i> |
| Log Lice Count |
| </button> |
| <button class="bg-green-100 text-green-800 py-4 rounded-lg font-medium flex flex-col items-center justify-center"> |
| <i data-feather="activity" class="w-8 h-8 mb-2"></i> |
| Record Mortality |
| </button> |
| <button class="bg-purple-100 text-purple-800 py-4 rounded-lg font-medium flex flex-col items-center justify-center"> |
| <i data-feather="calendar" class="w-8 h-8 mb-2"></i> |
| Plan Treatment |
| </button> |
| <button class="bg-orange-100 text-orange-800 py-4 rounded-lg font-medium flex flex-col items-center justify-center"> |
| <i data-feather="bar-chart-2" class="w-8 h-8 mb-2"></i> |
| View Reports |
| </button> |
| </div> |
| </section> |
|
|
| |
| <section class="p-4 mt-6" data-aos="fade-up"> |
| <h2 class="text-xl font-bold text-gray-800 mb-4 flex items-center"> |
| <i data-feather="alert-triangle" class="mr-2 text-orange-600"></i> |
| Alerts & Notifications |
| </h2> |
| |
| <div class="space-y-3"> |
| <div class="bg-white rounded-xl shadow-md p-4 border-l-4 border-orange-500"> |
| <div class="flex justify-between items-start"> |
| <h3 class="font-semibold">High Lice Count</h3> |
| <span class="text-xs text-gray-500">1 hour ago</span> |
| </div> |
| <p class="text-sm text-gray-600 mt-1">Pen #4: Average count 5.8 - exceeds threshold</p> |
| </div> |
| |
| <div class="bg-white rounded-xl shadow-md p-4 border-l-4 border-blue-500"> |
| <div class="flex justify-between items-start"> |
| <h3 class="font-semibold">Treatment Due</h3> |
| <span class="text-xs text-gray-500">3 hours ago</span> |
| </div> |
| <p class="text-sm text-gray-600 mt-1">Scheduled treatment for North Fjord starts tomorrow</p> |
| </div> |
| </div> |
| </section> |
| </main> |
|
|
| |
| <div id="liceModal" class="fixed inset-0 bg-black bg-opacity-50 hidden z-50 flex items-center justify-center p-4"> |
| <div class="bg-white rounded-2xl w-full max-w-md max-h-[90vh] overflow-y-auto"> |
| <div class="p-6"> |
| <div class="flex justify-between items-center mb-6"> |
| <h2 class="text-xl font-bold">Log Lice Count</h2> |
| <button onclick="closeModal()" class="text-gray-400 hover:text-gray-600"> |
| <i data-feather="x"></i> |
| </button> |
| </div> |
| |
| <div class="space-y-4"> |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-2">Select Pen</label> |
| <select class="w-full p-3 border border-gray-300 rounded-lg"> |
| <option>Pen #1 - 380 tons</option> |
| <option>Pen #2 - 420 tons</option> |
| <option>Pen #3 - 395 tons</option> |
| <option>Pen #4 - 410 tons</option> |
| </select> |
| </div> |
| |
| <div class="grid grid-cols-2 gap-3"> |
| <div class="text-center"> |
| <label class="block text-sm font-medium text-gray-700 mb-2">Chalimus</label> |
| <div class="stage-counter big-tap-button bg-blue-100 text-blue-800 rounded-lg flex items-center justify-center text-2xl font-bold" onclick="incrementCount(this)"> |
| 0 |
| </div> |
| </div> |
| <div class="text-center"> |
| <label class="block text-sm font-medium text-gray-700 mb-2">Preadult</label> |
| <div class="stage-counter big-tap-button bg-green-100 text-green-800 rounded-lg flex items-center justify-center text-2xl font-bold" onclick="incrementCount(this)"> |
| 0 |
| </div> |
| </div> |
| <div class="text-center"> |
| <label class="block text-sm font-medium text-gray-700 mb-2">Adult</label> |
| <div class="stage-counter big-tap-button bg-yellow-100 text-yellow-800 rounded-lg flex items-center justify-center text-2xl font-bold" onclick="incrementCount(this)"> |
| 0 |
| </div> |
| </div> |
| <div class="text-center"> |
| <label class="block text-sm font-medium text-gray-700 mb-2">Mobile</label> |
| <div class="stage-counter big-tap-button bg-purple-100 text-purple-800 rounded-lg flex items-center justify-center text-2xl font-bold" onclick="incrementCount(this)"> |
| 0 |
| </div> |
| </div> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-2">Water Temperature (°C)</label> |
| <input type="number" step="0.1" class="w-full p-3 border border-gray-300 rounded-lg" placeholder="12.5"> |
| </div> |
| |
| <div> |
| <label class="block text-sm font-medium text-gray-700 mb-2">Salinity (ppt)</label> |
| <input type="number" step="0.1" class="w-full p-3 border border-gray-300 rounded-lg" placeholder="32.5"> |
| </div> |
| |
| <button class="w-full bg-blue-600 text-white py-3 rounded-lg font-medium mt-4"> |
| Save Count |
| </button> |
| </div> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| |
| AOS.init({ |
| duration: 800, |
| once: true |
| }); |
| |
| |
| feather.replace(); |
| |
| |
| setTimeout(() => { |
| document.getElementById('offlineBanner').classList.remove('hidden'); |
| }, 2000); |
| |
| |
| function openLiceModal() { |
| document.getElementById('liceModal').classList.remove('hidden'); |
| } |
| |
| function closeModal() { |
| document.getElementById('liceModal').classList.add('hidden'); |
| } |
| |
| |
| function incrementCount(element) { |
| let count = parseInt(element.textContent); |
| element.textContent = count + 1; |
| } |
| |
| |
| document.getElementById('syncCount').textContent = '3'; |
| document.getElementById('syncCount').classList.remove('hidden'); |
| </script> |
| </body> |
| </html> |
|
|