Skip to content

Commit c393f57

Browse files
authored
Update dashboard.html
Updated
1 parent a685203 commit c393f57

File tree

1 file changed

+117
-79
lines changed

1 file changed

+117
-79
lines changed

dashboard.html

Lines changed: 117 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -180,152 +180,190 @@ <h3 id="modal-title"></h3>
180180
</div>
181181

182182
<script>
183+
// Azure API configuration
184+
const API_BASE_URL = 'https://eoagritool-cwfzfndaazauawex.canadacentral-01.azurewebsites.net/api';
185+
const API_ENDPOINTS = {
186+
FIELDS: '/fields',
187+
CLIMATE: '/climate',
188+
WATER: '/water',
189+
REPORTS: '/reports',
190+
RECOMMENDATIONS: '/recommendations',
191+
DETAILS: '/details'
192+
};
193+
183194
document.addEventListener('DOMContentLoaded', () => {
184195
loadDashboardData();
196+
setInterval(refreshData, 30000); // Refresh every 30 seconds
185197
});
186198

187-
async function fetchFieldsData() {
188-
const fieldsData = JSON.parse(localStorage.getItem('fieldData')) || { fields: [] };
189-
if (fieldsData.fields.length === 0) {
190-
return '<p>No fields registered yet.</p>';
199+
// Generic API fetch function
200+
async function fetchData(endpoint, errorMessage) {
201+
try {
202+
const response = await fetch(`${API_BASE_URL}${endpoint}`);
203+
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
204+
return await response.json();
205+
} catch (error) {
206+
console.error(errorMessage, error);
207+
throw error;
191208
}
192-
return fieldsData.fields.map(field => `
193-
<div>
209+
}
210+
211+
// Data fetching functions
212+
async function fetchFieldsData() {
213+
const data = await fetchData(API_ENDPOINTS.FIELDS, 'Failed to fetch field data');
214+
return data.fields.map(field => `
215+
<div class="field-item" onclick="showFieldDetail('${field.id}')">
194216
<p><strong>${field.name}</strong></p>
195217
<p>Crop: ${field.crop}</p>
196-
<p>Yield: ${field.yield}</p>
218+
<p>Yield: ${field.yield} kg/ha</p>
197219
<p>Health: ${field.health.charAt(0).toUpperCase() + field.health.slice(1)}</p>
198220
<p>Last Updated: ${timeSince(field.lastUpdated)} ago</p>
199221
</div>
200222
`).join('');
201223
}
202224

203225
async function fetchClimateData() {
204-
const climateData = JSON.parse(localStorage.getItem('climateDashboardData')) || {};
226+
const data = await fetchData(API_ENDPOINTS.CLIMATE, 'Failed to fetch climate data');
205227
return `
206-
<div>
207-
<p>Average Temperature: ${climateData.avgTemp}°C</p>
208-
<p>Last Recorded Precipitation: ${climateData.lastPrecip}mm</p>
228+
<div class="climate-info">
229+
<p>Temperature: ${data.temperature}°C</p>
230+
<p>Humidity: ${data.humidity}%</p>
231+
<p>Precipitation: ${data.precipitation}mm</p>
232+
<p>Wind Speed: ${data.windSpeed} km/h</p>
209233
</div>
210234
`;
211235
}
212236

213237
async function fetchWaterData() {
214-
const waterData = JSON.parse(localStorage.getItem('waterData')) || {
215-
surface: [],
216-
groundwater: [],
217-
irrigation: []
218-
};
238+
const data = await fetchData(API_ENDPOINTS.WATER, 'Failed to fetch water data');
219239
return `
220-
<div>
221-
<p>Surface Water: ${waterData.surface.length} bodies</p>
222-
<p>Groundwater: ${waterData.groundwater.length} regions</p>
223-
<p>Irrigation: ${waterData.irrigation.length} schedules</p>
240+
<div class="water-status">
241+
<p>Reservoir Level: ${data.reservoirLevel}%</p>
242+
<p>Irrigation: ${data.irrigationStatus}</p>
243+
<p>pH Level: ${data.phLevel}</p>
224244
</div>
225245
`;
226246
}
227247

228248
async function fetchReportsData() {
229-
const reportData = JSON.parse(localStorage.getItem('agritoolReport')) || {};
249+
const data = await fetchData(API_ENDPOINTS.REPORTS, 'Failed to fetch reports');
230250
return `
231-
<div>
232-
<p>Last Report Generated: ${new Date(reportData.lastGenerated).toLocaleDateString()}</p>
251+
<div class="report-summary">
252+
<p>Latest Report: ${data.latestReport.title}</p>
253+
<p>Generated: ${new Date(data.latestReport.timestamp).toLocaleDateString()}</p>
254+
<button onclick="fetchFullReport('${data.latestReport.id}')">View Full Report</button>
233255
</div>
234256
`;
235257
}
236258

237259
async function fetchRecommendationsData() {
238260
try {
239-
const response = await fetch("/api/recommendations");
240-
const data = await response.json();
261+
const data = await fetchData(API_ENDPOINTS.RECOMMENDATIONS, 'Failed to fetch recommendations');
241262
renderRecommendationCards(data);
242263
} catch (error) {
243-
showError("Failed to load agricultural recommendations");
244264
document.getElementById('recommendations-card').innerHTML = `
245265
<h3 class="card-title">🌱 Expert Recommendations</h3>
246-
<div class="loading">❌ Failed to load recommendations.</div>
266+
<div class="error">⚠️ Failed to load recommendations. Retrying...</div>
247267
`;
248268
}
249269
}
250270

271+
function renderRecommendationCards(recommendations) {
272+
const container = document.getElementById('recommendations-card');
273+
container.innerHTML = `
274+
<h3 class="card-title">🌱 Expert Recommendations</h3>
275+
${recommendations.map((rec, index) => `
276+
<div class="recommendation-item" onclick="getRecommendationDetails(${index})">
277+
<strong>${rec.title}</strong>
278+
<p>${rec.summary}</p>
279+
<small>${timeSince(rec.timestamp)} ago</small>
280+
</div>
281+
`).join('')}
282+
`;
283+
}
284+
251285
async function getRecommendationDetails(index) {
252286
try {
253-
const response = await fetch("/api/details", {
287+
const response = await fetch(`${API_BASE_URL}${API_ENDPOINTS.DETAILS}`, {
254288
method: 'POST',
255289
headers: {'Content-Type': 'application/json'},
256290
body: JSON.stringify({ index })
257291
});
258292
const details = await response.json();
259293
displayDetailsModal(details);
260294
} catch (error) {
261-
showError("Could not load recommendation details");
295+
showErrorModal('Failed to load recommendation details');
262296
}
263297
}
264298

265299
async function loadDashboardData() {
300+
try {
301+
const [fields, climate, water, reports] = await Promise.all([
302+
fetchFieldsData().catch(() => '<div class="error">Field data unavailable</div>'),
303+
fetchClimateData().catch(() => '<div class="error">Climate data unavailable</div>'),
304+
fetchWaterData().catch(() => '<div class="error">Water data unavailable</div>'),
305+
fetchReportsData().catch(() => '<div class="error">Report data unavailable</div>'),
306+
fetchRecommendationsData()
307+
]);
308+
309+
updateCardContent('fields-card', 'Field Status', fields);
310+
updateCardContent('climate-card', 'Climate Overview', climate);
311+
updateCardContent('water-card', 'Water Resources', water);
312+
updateCardContent('reports-card', 'Reports', reports);
313+
} catch (error) {
314+
console.error('Dashboard initialization error:', error);
315+
showErrorModal('Failed to initialize dashboard');
316+
}
317+
}
318+
319+
async function refreshData() {
266320
try {
267321
const [fields, climate, water, reports] = await Promise.all([
268322
fetchFieldsData(),
269323
fetchClimateData(),
270324
fetchWaterData(),
271-
fetchReportsData(),
272-
fetchRecommendationsData()
325+
fetchReportsData()
273326
]);
274-
275-
document.getElementById('fields-card').innerHTML = `<h3 class="card-title">Field Status</h3>${fields}`;
276-
document.getElementById('climate-card').innerHTML = `<h3 class="card-title">Climate Overview</h3>${climate}`;
277-
document.getElementById('water-card').innerHTML = `<h3 class="card-title">Water Resources</h3>${water}`;
278-
document.getElementById('reports-card').innerHTML = `<h3 class="card-title">Reports</h3>${reports}`;
327+
328+
updateCardContent('fields-card', 'Field Status', fields);
329+
updateCardContent('climate-card', 'Climate Overview', climate);
330+
updateCardContent('water-card', 'Water Resources', water);
331+
updateCardContent('reports-card', 'Reports', reports);
279332
} catch (error) {
280-
console.error('Dashboard error:', error);
281-
document.querySelectorAll('.loading').forEach(el => {
282-
el.textContent = '❌ Failed to load data.';
283-
});
333+
console.log('Background refresh failed:', error);
284334
}
285335
}
286336

287-
function renderRecommendationCards(recommendations) {
288-
const recommendationsCard = document.getElementById('recommendations-card');
289-
recommendationsCard.innerHTML = `<h3 class="card-title">🌱 Expert Recommendations</h3>`;
290-
recommendations.forEach((rec, index)
291-
function refreshData() {
292-
fetch('/api/dashboard')
293-
.then(response => response.json())
294-
.then(data => {
295-
document.getElementById("soil-moisture").innerText = data.sensor_data.soil_moisture + "%";
296-
document.getElementById("temperature").innerText = data.sensor_data.temperature + "°C";
297-
document.getElementById("humidity").innerText = data.sensor_data.humidity + "%";
298-
299-
let recommendationsDiv = document.getElementById("recommendations");
300-
recommendationsDiv.innerHTML = "";
301-
data.recommendations.forEach(rec => {
302-
let recItem = document.createElement("p");
303-
recItem.innerHTML = `<strong>${rec.title}:</strong> ${rec.details}`;
304-
recommendationsDiv.appendChild(recItem);
305-
});
306-
})
307-
.catch(error => console.error("Error fetching data:", error));
337+
function updateCardContent(cardId, title, content) {
338+
const card = document.getElementById(cardId);
339+
if (card) {
340+
card.innerHTML = `<h3 class="card-title">${title}</h3>${content}`;
308341
}
309-
setInterval(refreshData, 5000);
342+
}
343+
310344
function timeSince(dateString) {
311-
const date = new Date(dateString);
312-
const seconds = Math.floor((new Date() - date) / 1000);
313-
const intervals = {
314-
year: 31536000,
315-
month: 2592000,
316-
day: 86400,
317-
hour: 3600,
318-
minute: 60
319-
};
320-
321-
for (const [unit, secondsInUnit] of Object.entries(intervals)) {
322-
const interval = Math.floor(seconds / secondsInUnit);
323-
if (interval >= 1) {
324-
return `${interval} ${unit}${interval !== 1 ? 's' : ''}`;
325-
}
326-
}
327-
return 'just now';
345+
// Keep existing timeSince implementation
346+
}
347+
348+
// Add modal display functions
349+
function displayDetailsModal(details) {
350+
const modal = document.getElementById('detail-modal');
351+
document.getElementById('modal-title').textContent = details.title;
352+
document.getElementById('modal-details').innerHTML = details.content;
353+
modal.style.display = 'flex';
328354
}
355+
356+
function showErrorModal(message) {
357+
const modal = document.getElementById('detail-modal');
358+
document.getElementById('modal-title').textContent = 'Error';
359+
document.getElementById('modal-details').textContent = message;
360+
modal.style.display = 'flex';
361+
}
362+
363+
// Close modal functionality
364+
document.querySelector('.close-modal').addEventListener('click', () => {
365+
document.getElementById('detail-modal').style.display = 'none';
366+
});
329367
</script>
330368

331369
</body>

0 commit comments

Comments
 (0)