edenl14's picture
can you also help me with the backend and connection hugging face open source models for image analysis
7aea1a5 verified
raw
history blame
30.3 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ToxiTrack - Dashboard</title>
<link rel="icon" type="image/x-icon" href="/static/favicon.ico">
<script src="https://cdn.tailwindcss.com">
</script>
<!-- Modal for scan results -->
<div id="scanModal" class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center hidden z-50">
<div class="bg-white rounded-lg p-6 max-w-md w-full">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-bold text-gray-800">Scan Results</h3>
<button id="closeModal" class="text-gray-500 hover:text-gray-700">
<i data-feather="x"></i>
</button>
</div>
<div class="mb-4">
<img id="scanImage" src="" alt="Scanned Food" class="w-full h-48 object-cover rounded-lg mb-4">
<div class="grid grid-cols-2 gap-4">
<div>
<p class="text-sm text-gray-500">Toxin Level</p>
<p id="toxinLevel" class="font-bold"></p>
</div>
<div>
<p class="text-sm text-gray-500">Safety</p>
<p id="safetyLevel" class="font-bold"></p>
</div>
</div>
<div class="mt-4">
<p class="text-sm text-gray-500">Recommendation</p>
<p id="recommendation" class="text-sm"></p>
</div>
</div>
<button id="saveScan" class="w-full bg-emerald-500 hover:bg-emerald-600 text-white py-2 rounded-lg">
Save to History
</button>
</div>
</div>
<script>
// Modal functionality
const modal = document.getElementById('scanModal');
const closeModal = document.getElementById('closeModal');
const saveScan = document.getElementById('saveScan');
closeModal.addEventListener('click', () => {
modal.classList.add('hidden');
});
saveScan.addEventListener('click', () => {
// Here you would save the scan to your database
// For now we'll just close the modal and reload
modal.classList.add('hidden');
location.reload();
});
</script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
body {
font-family: 'Poppins', sans-serif;
}
.sidebar {
transition: all 0.3s ease;
}
.chart-container {
position: relative;
height: 300px;
width: 100%;
}
.toxin-level-low {
background-color: #10B981;
}
.toxin-level-medium {
background-color: #F59E0B;
}
.toxin-level-high {
background-color: #EF4444;
}
.active-tab {
border-bottom: 3px solid #10B981;
color: #10B981;
font-weight: 600;
}
</style>
</head>
<body class="bg-gray-50">
<div class="flex h-screen overflow-hidden">
<!-- Sidebar -->
<div class="sidebar bg-white w-64 border-r border-gray-200 flex-shrink-0 hidden md:block">
<div class="p-4 border-b border-gray-200">
<div class="flex items-center space-x-2">
<i data-feather="shield" class="text-emerald-500"></i>
<span class="text-xl font-bold text-gray-800">ToxiTrack</span>
</div>
</div>
<nav class="p-4">
<div class="mb-8">
<div class="flex items-center space-x-3 mb-6 p-3 rounded-lg bg-emerald-50">
<div class="w-10 h-10 rounded-full bg-emerald-100 flex items-center justify-center">
<i data-feather="user" class="text-emerald-500"></i>
</div>
<div>
<p class="font-medium text-gray-700">Welcome back</p>
<p class="text-sm text-gray-500">John Doe</p>
</div>
</div>
</div>
<div class="space-y-2">
<a href="index.html" class="flex items-center space-x-3 p-3 text-gray-600 hover:bg-gray-100 rounded-lg">
<i data-feather="home" class="w-5 h-5"></i>
<span>Home</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 bg-emerald-50 text-emerald-500 rounded-lg">
<i data-feather="activity" class="w-5 h-5"></i>
<span>Dashboard</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 text-gray-600 hover:bg-gray-100 rounded-lg">
<i data-feather="camera" class="w-5 h-5"></i>
<span>Food Scanner</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 text-gray-600 hover:bg-gray-100 rounded-lg">
<i data-feather="map-pin" class="w-5 h-5"></i>
<span>Air Quality</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 text-gray-600 hover:bg-gray-100 rounded-lg">
<i data-feather="trending-up" class="w-5 h-5"></i>
<span>Trends</span>
</a>
<a href="#" class="flex items-center space-x-3 p-3 text-gray-600 hover:bg-gray-100 rounded-lg">
<i data-feather="settings" class="w-5 h-5"></i>
<span>Settings</span>
</a>
</div>
</nav>
</div>
<!-- Main Content -->
<div class="flex-1 overflow-auto">
<!-- Mobile Header -->
<header class="bg-white border-b border-gray-200 p-4 flex items-center justify-between md:hidden">
<div class="flex items-center space-x-2">
<i data-feather="shield" class="text-emerald-500"></i>
<span class="text-lg font-bold text-gray-800">ToxiTrack</span>
</div>
<button id="mobile-menu-button">
<i data-feather="menu" class="w-6 h-6 text-gray-600"></i>
</button>
</header>
<!-- Dashboard Content -->
<main class="p-6">
<div class="flex justify-between items-center mb-8">
<h1 class="text-2xl font-bold text-gray-800">Health Dashboard</h1>
<div class="relative">
<select class="appearance-none bg-white border border-gray-300 rounded-lg py-2 pl-4 pr-8 text-gray-700 focus:outline-none focus:ring-2 focus:ring-emerald-500">
<option>Last 7 days</option>
<option>Last 30 days</option>
<option>Last 90 days</option>
<option>Last year</option>
<option>Custom range</option>
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
<i data-feather="chevron-down" class="w-4 h-4"></i>
</div>
</div>
</div>
<!-- Stats Overview -->
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 mb-8">
<div class="bg-white p-6 rounded-xl shadow-sm">
<div class="flex items-center justify-between mb-4">
<h3 class="text-gray-500 font-medium">Toxin Exposure</h3>
<div class="w-8 h-8 rounded-full bg-emerald-100 flex items-center justify-center">
<i data-feather="alert-triangle" class="text-emerald-500 w-4 h-4"></i>
</div>
</div>
<div class="flex items-end space-x-2">
<p class="text-3xl font-bold text-gray-800">24%</p>
<p class="text-sm text-emerald-500 flex items-center">
<i data-feather="arrow-down" class="w-4 h-4 mr-1"></i> 8% from last week
</p>
</div>
<div class="mt-4 bg-gray-200 rounded-full h-2">
<div class="bg-emerald-500 h-2 rounded-full" style="width: 24%"></div>
</div>
</div>
<div class="bg-white p-6 rounded-xl shadow-sm">
<div class="flex items-center justify-between mb-4">
<h3 class="text-gray-500 font-medium">Food Safety Score</h3>
<div class="w-8 h-8 rounded-full bg-blue-100 flex items-center justify-center">
<i data-feather="check-circle" class="text-blue-500 w-4 h-4"></i>
</div>
</div>
<div class="flex items-end space-x-2">
<p class="text-3xl font-bold text-gray-800">82</p>
<p class="text-sm text-blue-500 flex items-center">
<i data-feather="arrow-up" class="w-4 h-4 mr-1"></i> 5 from last week
</p>
</div>
<div class="mt-4 bg-gray-200 rounded-full h-2">
<div class="bg-blue-500 h-2 rounded-full" style="width: 82%"></div>
</div>
</div>
<div class="bg-white p-6 rounded-xl shadow-sm">
<div class="flex items-center justify-between mb-4">
<h3 class="text-gray-500 font-medium">Air Quality Index</h3>
<div class="w-8 h-8 rounded-full bg-yellow-100 flex items-center justify-center">
<i data-feather="wind" class="text-yellow-500 w-4 h-4"></i>
</div>
</div>
<div class="flex items-end space-x-2">
<p class="text-3xl font-bold text-gray-800">Moderate</p>
<p class="text-sm text-yellow-500 flex items-center">
<i data-feather="alert-circle" class="w-4 h-4 mr-1"></i> Sensitive groups
</p>
</div>
<div class="mt-4 bg-gray-200 rounded-full h-2">
<div class="bg-yellow-500 h-2 rounded-full" style="width: 65%"></div>
</div>
</div>
</div>
<!-- Tabs -->
<div class="border-b border-gray-200 mb-6">
<nav class="flex space-x-8">
<button class="py-4 px-1 active-tab">Overview</button>
<button class="py-4 px-1 text-gray-500 hover:text-gray-700">Food Analysis</button>
<button class="py-4 px-1 text-gray-500 hover:text-gray-700">Air Quality</button>
<button class="py-4 px-1 text-gray-500 hover:text-gray-700">Trends</button>
</nav>
</div>
<!-- Charts Section -->
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-8">
<!-- Main Chart -->
<div class="bg-white p-6 rounded-xl shadow-sm">
<div class="flex justify-between items-center mb-4">
<h3 class="font-semibold text-gray-800">Toxin Exposure Over Time</h3>
<div class="flex space-x-2">
<button class="text-xs px-3 py-1 rounded-full bg-emerald-100 text-emerald-600">Week</button>
<button class="text-xs px-3 py-1 rounded-full bg-gray-100 text-gray-600">Month</button>
<button class="text-xs px-3 py-1 rounded-full bg-gray-100 text-gray-600">Year</button>
</div>
</div>
<div class="chart-container">
<canvas id="mainChart"></canvas>
</div>
</div>
<!-- Toxin Sources -->
<div class="bg-white p-6 rounded-xl shadow-sm">
<h3 class="font-semibold text-gray-800 mb-4">Toxin Sources Breakdown</h3>
<div class="chart-container">
<canvas id="sourcesChart"></canvas>
</div>
</div>
</div>
<!-- Recent Scans -->
<div class="bg-white p-6 rounded-xl shadow-sm mb-8">
<div class="flex justify-between items-center mb-4">
<h3 class="font-semibold text-gray-800">Recent Food Scans</h3>
<button id="newScanButton" class="text-sm text-emerald-500 hover:text-emerald-600 flex items-center">
<i data-feather="plus" class="w-4 h-4 mr-1"></i> New Scan
</button>
<input type="file" id="fileInput" accept="image/*" class="hidden">
</div>
<div class="overflow-x-auto">
<table class="min-w-full divide-y divide-gray-200">
<thead>
<tr>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Food Item</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Toxin Level</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Date</th>
<th class="px-4 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Safety</th>
</tr>
</thead>
<tbody class="bg-white divide-y divide-gray-200">
<tr>
<td class="px-4 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<img class="h-10 w-10 rounded-full" src="http://static.photos/food/200x200/1" alt="">
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Organic Apples</div>
<div class="text-sm text-gray-500">Fruits</div>
</div>
</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Low</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Today, 09:42 AM</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-emerald-100 text-emerald-800">Safe</span>
</td>
</tr>
<tr>
<td class="px-4 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<img class="h-10 w-10 rounded-full" src="http://static.photos/food/200x200/2" alt="">
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Canned Tuna</div>
<div class="text-sm text-gray-500">Seafood</div>
</div>
</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Medium</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Yesterday, 07:15 PM</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-yellow-100 text-yellow-800">Caution</span>
</td>
</tr>
<tr>
<td class="px-4 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="flex-shrink-0 h-10 w-10">
<img class="h-10 w-10 rounded-full" src="http://static.photos/food/200x200/3" alt="">
</div>
<div class="ml-4">
<div class="text-sm font-medium text-gray-900">Processed Cheese</div>
<div class="text-sm text-gray-500">Dairy</div>
</div>
</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">High</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<div class="text-sm text-gray-900">Yesterday, 12:30 PM</div>
</td>
<td class="px-4 py-4 whitespace-nowrap">
<span class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">Avoid</span>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Air Quality Card -->
<div class="bg-white p-6 rounded-xl shadow-sm">
<div class="flex justify-between items-center mb-4">
<h3 class="font-semibold text-gray-800">Current Air Quality</h3>
<div class="flex items-center">
<i data-feather="map-pin" class="w-4 h-4 text-gray-500 mr-1"></i>
<span class="text-sm text-gray-600">New York, NY</span>
</div>
</div>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div class="bg-blue-50 p-4 rounded-lg">
<div class="flex items-center justify-between mb-2">
<span class="text-sm text-blue-600">PM2.5</span>
<span class="text-sm font-medium text-blue-600">12 µg/m³</span>
</div>
<div class="h-2 bg-blue-200 rounded-full">
<div class="h-2 bg-blue-500 rounded-full" style="width: 24%"></div>
</div>
<p class="text-xs text-blue-600 mt-1">Good</p>
</div>
<div class="bg-yellow-50 p-4 rounded-lg">
<div class="flex items-center justify-between mb-2">
<span class="text-sm text-yellow-600">Ozone</span>
<span class="text-sm font-medium text-yellow-600">68 ppb</span>
</div>
<div class="h-2 bg-yellow-200 rounded-full">
<div class="h-2 bg-yellow-500 rounded-full" style="width: 68%"></div>
</div>
<p class="text-xs text-yellow-600 mt-1">Moderate</p>
</div>
<div class="bg-red-50 p-4 rounded-lg">
<div class="flex items-center justify-between mb-2">
<span class="text-sm text-red-600">NO2</span>
<span class="text-sm font-medium text-red-600">42 ppb</span>
</div>
<div class="h-2 bg-red-200 rounded-full">
<div class="h-2 bg-red-500 rounded-full" style="width: 42%"></div>
</div>
<p class="text-xs text-red-600 mt-1">Unhealthy for Sensitive</p>
</div>
</div>
<div class="mt-6 chart-container">
<canvas id="airQualityChart"></canvas>
</div>
</div>
</main>
</div>
</div>
<script>
feather.replace();
// Scan functionality
document.getElementById('newScanButton').addEventListener('click', () => {
document.getElementById('fileInput').click();
});
document.getElementById('fileInput').addEventListener('change', async (e) => {
const file = e.target.files[0];
if (!file) return;
// Show loading state
const button = document.getElementById('newScanButton');
button.innerHTML = '<i data-feather="loader" class="w-4 h-4 mr-1 animate-spin"></i> Analyzing...';
feather.replace();
try {
// Upload image to backend for analysis
const formData = new FormData();
formData.append('image', file);
const response = await fetch('/api/analyze', {
method: 'POST',
body: formData
});
if (!response.ok) throw new Error('Analysis failed');
const result = await response.json();
// Display results (you would update this with your actual UI)
alert(`Analysis complete!\n\nToxin Level: ${result.toxin_level}\nSafety: ${result.safety}\nRecommendation: ${result.recommendation}`);
// Here you would update the recent scans table with the new result
// For now we'll just reload the page
location.reload();
} catch (error) {
console.error('Error:', error);
alert('Failed to analyze image. Please try again.');
} finally {
// Reset button
button.innerHTML = '<i data-feather="plus" class="w-4 h-4 mr-1"></i> New Scan';
feather.replace();
e.target.value = ''; // Clear file input
}
});
// Initialize charts
document.addEventListener('DOMContentLoaded', function() {
// Main Chart
const mainCtx = document.getElementById('mainChart').getContext('2d');
const mainChart = new Chart(mainCtx, {
type: 'line',
data: {
labels: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
datasets: [{
label: 'Toxin Exposure',
data: [30, 25, 35, 28, 22, 40, 24],
borderColor: '#10B981',
backgroundColor: 'rgba(16, 185, 129, 0.1)',
borderWidth: 2,
tension: 0.3,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true,
grid: {
display: true,
color: 'rgba(0, 0, 0, 0.05)'
}
},
x: {
grid: {
display: false
}
}
}
}
});
// Sources Chart
const sourcesCtx = document.getElementById('sourcesChart').getContext('2d');
const sourcesChart = new Chart(sourcesCtx, {
type: 'doughnut',
data: {
labels: ['Food', 'Air', 'Water', 'Household'],
datasets: [{
data: [45, 30, 15, 10],
backgroundColor: [
'#10B981',
'#3B82F6',
'#F59E0B',
'#EF4444'
],
borderWidth: 0
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
cutout: '70%',
plugins: {
legend: {
position: 'bottom'
}
}
}
});
// Air Quality Chart
const airCtx = document.getElementById('airQualityChart').getContext('2d');
const airChart = new Chart(airCtx, {
type: 'bar',
data: {
labels: ['12AM', '3AM', '6AM', '9AM', '12PM', '3PM', '6PM', '9PM'],
datasets: [{
label: 'Air Quality Index',
data: [35, 30, 42, 55, 68, 72, 60, 45],
backgroundColor: [
'#10B981',
'#10B981',
'#F59E0B',
'#F59E0B',
'#EF4444',
'#EF4444',
'#F59E0B',
'#F59E0B'
],
borderRadius: 6
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
}
},
scales: {
y: {
beginAtZero: true,
grid: {
display: true,
color: 'rgba(0, 0, 0, 0.05)'
}
},
x: {
grid: {
display: false
}
}
}
}
});
// Mobile menu toggle
const mobileMenuButton = document.getElementById('mobile-menu-button');
const sidebar = document.querySelector('.sidebar');
mobileMenuButton.addEventListener('click', function() {
sidebar.classList.toggle('hidden');
});
// Tab functionality
const tabs = document.querySelectorAll('.border-b button');
tabs.forEach(tab => {
tab.addEventListener('click', function() {
tabs.forEach(t => t.classList.remove('active-tab'));
tabs.forEach(t => t.classList.add('text-gray-500', 'hover:text-gray-700'));
this.classList.add('active-tab');
this.classList.remove('text-gray-500', 'hover:text-gray-700');
});
});
});
</script>
</body>
</html>