@@ -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