far / analytics.html
DRV2ME's picture
from fastapi import APIRouter, WebSocket, WebSocketDisconnect
75eac86 verified
Raw
History Blame Contribute Delete
12.2 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Analytics - Agrosynth OS</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<style>
.chart-container {
height: 300px;
}
</style>
</head>
<body class="bg-gray-50 font-sans antialiased">
<div class="flex h-screen overflow-hidden">
<!-- Sidebar -->
<div class="bg-white shadow-md w-64 flex flex-col">
<div class="flex items-center justify-center h-16 px-4 border-b">
<div class="flex items-center">
<i data-feather="layers" class="text-green-600 h-6 w-6"></i>
<span class="ml-2 text-lg font-bold text-gray-900">Agrosynth OS</span>
</div>
</div>
<nav class="flex-1 overflow-y-auto py-4">
<div class="px-4 space-y-1">
<a href="/dashboard" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i data-feather="home" class="text-gray-500 h-5 w-5"></i>
<span class="ml-3">Dashboard</span>
</a>
<a href="/field-maps" class="flex items-center px-2 py-2 text-sm font-medium rounded-md text-gray-600 hover:bg-gray-50 hover:text-gray-900">
<i data-feather="map" class="text-gray-500 h-5 w-5"></i>
<span class="ml-3">Field Maps</span>
</a>
<a href="/analytics" class="flex items-center px-2 py-2 text-sm font-medium rounded-md bg-green-50 text-green-700">
<i data-feather="activity" class="text-green-600 h-5 w-5"></i>
<span class="ml-3">Analytics</span>
</a>
</div>
</nav>
</div>
<!-- Main content -->
<div class="flex-1 overflow-auto">
<header class="bg-white shadow-sm">
<div class="flex justify-between items-center px-4 py-4 sm:px-6">
<h1 class="text-xl font-semibold text-gray-900">Analytics</h1>
</div>
</header>
<main class="p-4 sm:p-6">
<div id="analytics-container">
<div class="rounded-xl border p-6 text-sm text-gray-500">Loading analytics...</div>
</div>
</main>
</div>
</div>
<script>
feather.replace();
// Fetch analytics data with error handling
(async () => {
try {
const r = await fetch('/api/proxy/api/v1/farms/analytics');
const text = await r.text();
const data = JSON.parse(text);
const container = document.getElementById('analytics-container');
container.innerHTML = `
<h1 class="text-2xl font-semibold mb-4">Analytics</h1>
<div class="grid md:grid-cols-2 gap-6">
<div class="border rounded-xl p-4">
<div class="font-semibold mb-2">Yield Trend (t/ha)</div>
<div class="chart-container">
<canvas id="yieldChart"></canvas>
</div>
</div>
<div class="border rounded-xl p-4">
<div class="font-semibold mb-2">Soil Moisture (%)</div>
<div class="chart-container">
<canvas id="moistureChart"></canvas>
</div>
</div>
</div>
`;
// Yield Chart
const yieldCtx = document.getElementById('yieldChart').getContext('2d');
new Chart(yieldCtx, {
type: 'line',
data: {
labels: data.yield.labels,
datasets: [{
label: 'Yield (t/ha)',
data: data.yield.values,
borderColor: '#22c55e',
backgroundColor: 'rgba(34, 197, 94, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: (context) => `${context.dataset.label}: ${context.parsed.y} t/ha`
}
}
},
scales: {
y: {
beginAtZero: false,
min: Math.min(...data.yield.values) - 0.5,
max: Math.max(...data.yield.values) + 0.5
}
}
}
});
// Moisture Chart
const moistureCtx = document.getElementById('moistureChart').getContext('2d');
new Chart(moistureCtx, {
type: 'line',
data: {
labels: data.moisture.labels,
datasets: [{
label: 'Soil Moisture (%)',
data: data.moisture.values,
borderColor: '#3b82f6',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: (context) => `${context.dataset.label}: ${context.parsed.y}%`
}
}
},
scales: {
y: {
beginAtZero: false,
min: Math.min(...data.moisture.values) - 5,
max: Math.max(...data.moisture.values) + 5
}
}
}
});
})
// Render charts with the data
const container = document.getElementById('analytics-container');
container.innerHTML = `
<h1 class="text-2xl font-semibold mb-4">Analytics</h1>
<div class="grid md:grid-cols-2 gap-6">
<div class="border rounded-xl p-4">
<div class="font-semibold mb-2">Yield Trend (t/ha)</div>
<div class="chart-container">
<canvas id="yieldChart"></canvas>
</div>
</div>
<div class="border rounded-xl p-4">
<div class="font-semibold mb-2">Soil Moisture (%)</div>
<div class="chart-container">
<canvas id="moistureChart"></canvas>
</div>
</div>
</div>
`;
// Yield Chart
const yieldCtx = document.getElementById('yieldChart').getContext('2d');
new Chart(yieldCtx, {
type: 'line',
data: {
labels: data.yield.labels,
datasets: [{
label: 'Yield (t/ha)',
data: data.yield.values,
borderColor: '#22c55e',
backgroundColor: 'rgba(34, 197, 94, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: (context) => `${context.dataset.label}: ${context.parsed.y} t/ha`
}
}
},
scales: {
y: {
beginAtZero: false,
min: Math.min(...data.yield.values) - 0.5,
max: Math.max(...data.yield.values) + 0.5
}
}
}
});
// Moisture Chart
const moistureCtx = document.getElementById('moistureChart').getContext('2d');
new Chart(moistureCtx, {
type: 'line',
data: {
labels: data.moisture.labels,
datasets: [{
label: 'Soil Moisture (%)',
data: data.moisture.values,
borderColor: '#3b82f6',
backgroundColor: 'rgba(59, 130, 246, 0.1)',
borderWidth: 2,
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
label: (context) => `${context.dataset.label}: ${context.parsed.y}%`
}
}
},
scales: {
y: {
beginAtZero: false,
min: Math.min(...data.moisture.values) - 5,
max: Math.max(...data.moisture.values) + 5
}
}
}
});
} catch (e) {
const container = document.getElementById('analytics-container');
container.innerHTML = `
<div class="rounded-xl border p-6">
<h1 class="text-2xl font-semibold mb-4">Analytics</h1>
<div class="text-red-600">
Failed to load analytics data: ${e}
</div>
<button onclick="window.location.reload()"
class="mt-4 px-4 py-2 bg-primary-600 text-white rounded hover:bg-primary-700">
Retry
</button>
</div>
`;
}
})();
</script>
</body>
</html>