rajkhanke commited on
Commit
a504ef1
·
verified ·
1 Parent(s): 15dc575

Update templates/index.html

Browse files
Files changed (1) hide show
  1. templates/index.html +389 -372
templates/index.html CHANGED
@@ -1,372 +1,389 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="UTF-8" />
5
- <meta name="viewport" content="width=device-width, initial-scale=1" />
6
- <title>Pest Outbreak Prediction System</title>
7
- <!-- Bootstrap CSS (for grid utilities) -->
8
- <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
9
- <!-- Tailwind CSS CDN for advanced styling -->
10
- <script src="https://cdn.tailwindcss.com"></script>
11
- <!-- Leaflet CSS for map -->
12
- <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
13
- <!-- Leaflet Control Geocoder CSS for search bar -->
14
- <link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css" />
15
- <style>
16
- body {
17
- background: #f2f2f2; /* light grey to match final report page */
18
- margin: 0;
19
- padding: 0;
20
- }
21
- .container-custom {
22
- max-width: 1200px;
23
- margin: 2rem auto;
24
- padding: 1rem;
25
- background: #ffffff;
26
- border-radius: 8px;
27
- box-shadow: 0 4px 12px rgba(0,0,0,0.1);
28
- }
29
- #map {
30
- height: 400px;
31
- border-radius: 0.75rem;
32
- box-shadow: 0 8px 16px rgba(0,0,0,0.1);
33
- }
34
- .form-section {
35
- background: #ffffff;
36
- border-radius: 0.75rem;
37
- box-shadow: 0 8px 16px rgba(0,0,0,0.1);
38
- padding: 2rem;
39
- margin-bottom: 1.5rem;
40
- transition: transform 0.3s ease, box-shadow 0.3s ease;
41
- }
42
- .form-section:hover {
43
- transform: translateY(-4px);
44
- box-shadow: 0 12px 24px rgba(0,0,0,0.15);
45
- }
46
- h1, h4 {
47
- color: #2e7d32;
48
- text-align: center;
49
- }
50
- /* Weather Card Styles */
51
- .weather-card {
52
- background: #ffffff;
53
- border-radius: 0.5rem;
54
- box-shadow: 0 4px 8px rgba(0,0,0,0.1);
55
- padding: 1rem;
56
- text-align: center;
57
- transition: transform 0.2s;
58
- }
59
- .weather-card:hover {
60
- transform: translateY(-4px);
61
- }
62
- .weather-title {
63
- font-weight: 600;
64
- color: #2e7d32;
65
- margin-bottom: 0.5rem;
66
- }
67
- /* Soil properties table styling */
68
- #soilPropertiesTable table {
69
- width: 100%;
70
- border-collapse: collapse;
71
- }
72
- #soilPropertiesTable th, #soilPropertiesTable td {
73
- padding: 0.75rem;
74
- border: 1px solid #e2e8f0;
75
- text-align: center;
76
- }
77
- #soilPropertiesTable th {
78
- background-color: #81c784;
79
- color: #fff;
80
- }
81
- </style>
82
- </head>
83
- <body>
84
- <div class="container container-custom py-8">
85
- <h1 class="text-4xl font-bold mb-8">Pest Outbreak Prediction System</h1>
86
- <!-- The form submits to /predict to generate a detailed pest outbreak report -->
87
- <form id="farmForm" action="/predict" method="post">
88
- <!-- Map & Manual Inputs -->
89
- <div class="form-section">
90
- <h4 class="text-2xl font-semibold mb-4">Select Farm Location</h4>
91
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
92
- <!-- Left: Satellite map with search bar -->
93
- <div>
94
- <div id="map"></div>
95
- </div>
96
- <!-- Right: Manual lat/lon input -->
97
- <div class="flex flex-col justify-center space-y-4 p-4">
98
- <div>
99
- <label class="font-medium" for="manual_lat">Latitude:</label>
100
- <input type="number" step="0.000001" id="manual_lat" class="form-control" placeholder="Enter latitude" />
101
- </div>
102
- <div>
103
- <label class="font-medium" for="manual_lon">Longitude:</label>
104
- <input type="number" step="0.000001" id="manual_lon" class="form-control" placeholder="Enter longitude" />
105
- </div>
106
- <button type="button" id="updateLocationBtn" class="btn btn-primary shadow-md hover:shadow-lg transition duration-300">
107
- Update Location
108
- </button>
109
- </div>
110
- </div>
111
- <!-- Hidden fields to store final lat/lon -->
112
- <input type="hidden" id="latitude" name="latitude" />
113
- <input type="hidden" id="longitude" name="longitude" />
114
- </div>
115
-
116
- <!-- Weather Data Display -->
117
- <div class="form-section">
118
- <h4 class="text-2xl font-semibold mb-4">Weather Data</h4>
119
- <div id="weatherDataContainer" class="grid grid-cols-1 md:grid-cols-4 gap-4">
120
- <div class="col-span-full text-center text-gray-600">
121
- Weather data will appear here after you select or update a location.
122
- </div>
123
- </div>
124
- </div>
125
-
126
- <!-- Soil Data Section -->
127
- <div class="form-section" id="soilPropertiesTable">
128
- <h4 class="text-2xl font-semibold mb-4">Soil Nutrient Parameters</h4>
129
- <div id="soilTableContainer">
130
- <p class="text-center text-gray-600">Fetching soil data...</p>
131
- </div>
132
- </div>
133
-
134
- <!-- Additional Agricultural Inputs -->
135
- <div class="form-section">
136
- <h4 class="text-2xl font-semibold mb-4">Additional Agricultural Inputs</h4>
137
- <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
138
- <div>
139
- <label class="font-medium" for="crop_type">Crop Type:</label>
140
- <select class="form-control" id="crop_type" name="crop_type">
141
- <option value="rice">Rice</option>
142
- <option value="wheat">Wheat</option>
143
- <option value="maize">Maize</option>
144
- <option value="cotton">Cotton</option>
145
- <option value="sugarcane">Sugarcane</option>
146
- <option value="soybean">Soybean</option>
147
- <option value="millet">Millet</option>
148
- <option value="pulses">Pulses</option>
149
- <option value="potato">Potato</option>
150
- <option value="tomato">Tomato</option>
151
- <option value="onion">Onion</option>
152
- <option value="garlic">Garlic</option>
153
- <option value="groundnut">Groundnut</option>
154
- <option value="barley">Barley</option>
155
- <option value="jute">Jute</option>
156
- <option value="tea">Tea</option>
157
- <option value="coffee">Coffee</option>
158
- <option value="sorghum">Sorghum</option>
159
- <option value="turmeric">Turmeric</option>
160
- <option value="ginger">Ginger</option>
161
- </select>
162
- </div>
163
- <div>
164
- <label class="font-medium" for="sowing_date">Plant Sowing Date:</label>
165
- <input type="date" class="form-control" id="sowing_date" name="sowing_date" />
166
- </div>
167
- <div>
168
- <label class="font-medium" for="harvest_date">Expected Harvest Date:</label>
169
- <input type="date" class="form-control" id="harvest_date" name="harvest_date" />
170
- </div>
171
- <div>
172
- <label class="font-medium" for="growth_stage">Current Growth Stage:</label>
173
- <select class="form-control" id="growth_stage" name="growth_stage">
174
- <option value="sowing">Sowing</option>
175
- <option value="germination">Germination</option>
176
- <option value="vegetative">Vegetative</option>
177
- <option value="flowering">Flowering</option>
178
- <option value="fruiting">Fruiting</option>
179
- <option value="harvest">Harvest</option>
180
- </select>
181
- </div>
182
- <div>
183
- <label class="font-medium" for="irrigation_freq">Irrigation Frequency:</label>
184
- <select class="form-control" id="irrigation_freq" name="irrigation_freq">
185
- <option value="daily">Daily</option>
186
- <option value="alternate">Alternate Day</option>
187
- <option value="twice_week">Twice a Week</option>
188
- <option value="weekly">Weekly</option>
189
- </select>
190
- </div>
191
- <div>
192
- <label class="font-medium" for="irrigation_method">Irrigation Method:</label>
193
- <select class="form-control" id="irrigation_method" name="irrigation_method">
194
- <option value="drip">Drip</option>
195
- <option value="sprinkler">Sprinkler</option>
196
- <option value="flood">Flood</option>
197
- <option value="manual">Manual</option>
198
- </select>
199
- </div>
200
- <div>
201
- <label class="font-medium" for="soil_type">Soil Type:</label>
202
- <select class="form-control" id="soil_type" name="soil_type">
203
- <option value="red">Red</option>
204
- <option value="black">Black</option>
205
- <option value="clay">Clay</option>
206
- <option value="sandy">Sandy</option>
207
- <option value="loamy">Loamy</option>
208
- </select>
209
- </div>
210
- </div>
211
- </div>
212
-
213
- <!-- Hidden Fields for passing Weather data to Gemini -->
214
- <input type="hidden" id="max_temp_hidden" name="max_temp" />
215
- <input type="hidden" id="min_temp_hidden" name="min_temp" />
216
- <input type="hidden" id="current_temp_hidden" name="current_temp" />
217
- <input type="hidden" id="humidity_hidden" name="humidity" />
218
- <input type="hidden" id="rainfall_hidden" name="rain" />
219
- <input type="hidden" id="soil_moisture_hidden" name="soil_moisture" />
220
- <input type="hidden" id="wind_speed_hidden" name="wind_speed" />
221
- <input type="hidden" id="cloud_cover_hidden" name="cloud_cover" />
222
-
223
- <div class="form-section text-center">
224
- <button type="submit" class="btn btn-success btn-lg shadow-xl transform hover:scale-105 transition duration-300">
225
- Predict Pest Outbreak
226
- </button>
227
- </div>
228
- </form>
229
- </div>
230
-
231
- <!-- Scripts -->
232
- <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
233
- <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
234
- <!-- Leaflet JS -->
235
- <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
236
- <!-- Leaflet Control Geocoder JS for search -->
237
- <script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
238
- <script>
239
- // Initialize the map using Esri's World Imagery (satellite view)
240
- var map = L.map('map').setView([20.5937, 78.9629], 5);
241
- L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
242
- attribution: 'Tiles © Esri',
243
- maxZoom: 18,
244
- }).addTo(map);
245
-
246
- // Explicitly define the geocoder provider using Nominatim
247
- var geocoder = L.Control.Geocoder.nominatim();
248
-
249
- // Add geocoder (search bar) to the map with the provider
250
- L.Control.geocoder({
251
- geocoder: geocoder,
252
- defaultMarkGeocode: false
253
- })
254
- .on('markgeocode', function(e) {
255
- var bbox = e.geocode.bbox;
256
- var center = e.geocode.center;
257
- map.fitBounds(bbox);
258
- setMarker(center);
259
- })
260
- .addTo(map);
261
-
262
- var marker;
263
- function setMarker(latlng) {
264
- if (marker) {
265
- marker.setLatLng(latlng);
266
- } else {
267
- marker = L.marker(latlng).addTo(map);
268
- }
269
- // Update both hidden and manual fields
270
- document.getElementById('latitude').value = latlng.lat.toFixed(6);
271
- document.getElementById('longitude').value = latlng.lng.toFixed(6);
272
- document.getElementById('manual_lat').value = latlng.lat.toFixed(6);
273
- document.getElementById('manual_lon').value = latlng.lng.toFixed(6);
274
-
275
- // Fetch weather and soil data
276
- fetchWeatherData(latlng.lat, latlng.lng);
277
- fetchSoilProperties(latlng.lat, latlng.lng);
278
- }
279
-
280
- map.on('click', function(e) {
281
- setMarker(e.latlng);
282
- });
283
-
284
- // Update location using manual input
285
- document.getElementById('updateLocationBtn').addEventListener('click', function(){
286
- const lat = parseFloat(document.getElementById('manual_lat').value);
287
- const lon = parseFloat(document.getElementById('manual_lon').value);
288
- if(!isNaN(lat) && !isNaN(lon)){
289
- const latlng = L.latLng(lat, lon);
290
- map.setView(latlng, 10);
291
- setMarker(latlng);
292
- } else {
293
- alert("Please enter valid latitude and longitude values.");
294
- }
295
- });
296
-
297
- // Fetch weather data from backend (/get_weather_data)
298
- function fetchWeatherData(lat, lng) {
299
- fetch(`/get_weather_data?lat=${lat}&lon=${lng}`)
300
- .then(response => response.json())
301
- .then(data => {
302
- // Update the weather card container
303
- const container = document.getElementById('weatherDataContainer');
304
- container.innerHTML = `
305
- <div class="weather-card">
306
- <div class="weather-title">Max Temp</div>
307
- <div>${data.max_temp !== null ? data.max_temp + " °C" : "Not available"}</div>
308
- </div>
309
- <div class="weather-card">
310
- <div class="weather-title">Min Temp</div>
311
- <div>${data.min_temp !== null ? data.min_temp + " °C" : "Not available"}</div>
312
- </div>
313
- <div class="weather-card">
314
- <div class="weather-title">Current Temp</div>
315
- <div>${data.current_temp !== null ? data.current_temp + " °C" : "Not available"}</div>
316
- </div>
317
- <div class="weather-card">
318
- <div class="weather-title">Humidity</div>
319
- <div>${data.humidity !== null ? data.humidity.toFixed(1) + " %" : "Not available"}</div>
320
- </div>
321
- <div class="weather-card">
322
- <div class="weather-title">Rain</div>
323
- <div>${data.rainfall !== null ? data.rainfall + " mm" : "Not available"}</div>
324
- </div>
325
- <div class="weather-card">
326
- <div class="weather-title">Soil Moisture</div>
327
- <div>${data.soil_moisture !== null ? data.soil_moisture.toFixed(1) + " %" : "Not available"}</div>
328
- </div>
329
- <div class="weather-card">
330
- <div class="weather-title">Wind Speed</div>
331
- <div>${data.wind_speed !== null ? data.wind_speed + " km/h" : "Not available"}</div>
332
- </div>
333
- <div class="weather-card">
334
- <div class="weather-title">Cloud Cover</div>
335
- <div>${data.cloud_cover !== null ? data.cloud_cover.toFixed(1) + " %" : "Not available"}</div>
336
- </div>
337
- `;
338
-
339
- // Also store these values in hidden fields so they pass to Gemini
340
- document.getElementById('max_temp_hidden').value = data.max_temp ?? "";
341
- document.getElementById('min_temp_hidden').value = data.min_temp ?? "";
342
- document.getElementById('current_temp_hidden').value = data.current_temp ?? "";
343
- document.getElementById('humidity_hidden').value = data.humidity ?? "";
344
- document.getElementById('rainfall_hidden').value = data.rainfall ?? "";
345
- document.getElementById('soil_moisture_hidden').value = data.soil_moisture ?? "";
346
- document.getElementById('wind_speed_hidden').value = data.wind_speed ?? "";
347
- document.getElementById('cloud_cover_hidden').value = data.cloud_cover ?? "";
348
- })
349
- .catch(error => console.error('Error fetching weather data:', error));
350
- }
351
-
352
- // Fetch soil properties from backend (/get_soil_properties)
353
- function fetchSoilProperties(lat, lng) {
354
- fetch(`/get_soil_properties?lat=${lat}&lon=${lng}`)
355
- .then(response => response.json())
356
- .then(data => {
357
- if(data.soil_properties) {
358
- let tableHTML = "<table><thead><tr><th>Parameter</th><th>Value</th><th>Unit</th></tr></thead><tbody>";
359
- data.soil_properties.forEach(function(item) {
360
- tableHTML += `<tr><td>${item[0]}</td><td>${item[1]}</td><td>${item[2]}</td></tr>`;
361
- });
362
- tableHTML += "</tbody></table>";
363
- document.getElementById("soilTableContainer").innerHTML = tableHTML;
364
- } else {
365
- document.getElementById("soilTableContainer").innerHTML = "<p class='text-center text-gray-600'>No soil data available.</p>";
366
- }
367
- })
368
- .catch(error => console.error('Error fetching soil properties:', error));
369
- }
370
- </script>
371
- </body>
372
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Pest Outbreak Prediction System</title>
7
+ <!-- Bootstrap CSS (for grid utilities) -->
8
+ <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet" />
9
+ <!-- Tailwind CSS CDN for advanced styling -->
10
+ <script src="https://cdn.tailwindcss.com"></script>
11
+ <!-- Leaflet CSS for map -->
12
+ <link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css" />
13
+ <!-- Leaflet Control Geocoder CSS for search bar -->
14
+ <link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css" />
15
+ <style>
16
+ body {
17
+ background: #f2f2f2; /* light grey to match final report page */
18
+ margin: 0;
19
+ padding: 0;
20
+ }
21
+ .container-custom {
22
+ max-width: 1200px;
23
+ margin: 2rem auto;
24
+ padding: 1rem;
25
+ background: #ffffff;
26
+ border-radius: 8px;
27
+ box-shadow: 0 4px 12px rgba(0,0,0,0.1);
28
+ }
29
+ #map {
30
+ height: 400px;
31
+ border-radius: 0.75rem;
32
+ box-shadow: 0 8px 16px rgba(0,0,0,0.1);
33
+ }
34
+ .form-section {
35
+ background: #ffffff;
36
+ border-radius: 0.75rem;
37
+ box-shadow: 0 8px 16px rgba(0,0,0,0.1);
38
+ padding: 2rem;
39
+ margin-bottom: 1.5rem;
40
+ transition: transform 0.3s ease, box-shadow 0.3s ease;
41
+ }
42
+ .form-section:hover {
43
+ transform: translateY(-4px);
44
+ box-shadow: 0 12px 24px rgba(0,0,0,0.15);
45
+ }
46
+ h1, h4 {
47
+ color: #2e7d32;
48
+ text-align: center;
49
+ }
50
+ /* Weather Card Styles */
51
+ .weather-card {
52
+ background: #ffffff;
53
+ border-radius: 0.5rem;
54
+ box-shadow: 0 4px 8px rgba(0,0,0,0.1);
55
+ padding: 1rem;
56
+ text-align: center;
57
+ transition: transform 0.2s;
58
+ }
59
+ .weather-card:hover {
60
+ transform: translateY(-4px);
61
+ }
62
+ .weather-title {
63
+ font-weight: 600;
64
+ color: #2e7d32;
65
+ margin-bottom: 0.5rem;
66
+ }
67
+ /* Soil properties table styling */
68
+ #soilPropertiesTable table {
69
+ width: 100%;
70
+ border-collapse: collapse;
71
+ }
72
+ #soilPropertiesTable th, #soilPropertiesTable td {
73
+ padding: 0.75rem;
74
+ border: 1px solid #e2e8f0;
75
+ text-align: center;
76
+ }
77
+ #soilPropertiesTable th {
78
+ background-color: #81c784;
79
+ color: #fff;
80
+ }
81
+ </style>
82
+ </head>
83
+ <body>
84
+ <div class="container container-custom py-8">
85
+ <h1 class="text-4xl font-bold mb-8">Pest Outbreak Prediction System</h1>
86
+ <!-- The form submits to /predict to generate a detailed pest outbreak report -->
87
+ <form id="farmForm" action="/predict" method="post">
88
+ <!-- Map & Manual Inputs -->
89
+ <div class="form-section">
90
+ <h4 class="text-2xl font-semibold mb-4">Select Farm Location</h4>
91
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
92
+ <!-- Left: Satellite map with search bar -->
93
+ <div>
94
+ <div id="map"></div>
95
+ </div>
96
+ <!-- Right: Manual lat/lon input -->
97
+ <div class="flex flex-col justify-center space-y-4 p-4">
98
+ <div>
99
+ <label class="font-medium" for="manual_lat">Latitude:</label>
100
+ <input type="number" step="0.000001" id="manual_lat" class="form-control" placeholder="Enter latitude" />
101
+ </div>
102
+ <div>
103
+ <label class="font-medium" for="manual_lon">Longitude:</label>
104
+ <input type="number" step="0.000001" id="manual_lon" class="form-control" placeholder="Enter longitude" />
105
+ </div>
106
+ <button type="button" id="updateLocationBtn" class="btn btn-primary shadow-md hover:shadow-lg transition duration-300">
107
+ Update Location
108
+ </button>
109
+ </div>
110
+ </div>
111
+ <!-- Hidden fields to store final lat/lon -->
112
+ <input type="hidden" id="latitude" name="latitude" />
113
+ <input type="hidden" id="longitude" name="longitude" />
114
+ </div>
115
+
116
+ <!-- Weather Data Display -->
117
+ <div class="form-section">
118
+ <h4 class="text-2xl font-semibold mb-4">Weather Data</h4>
119
+ <div id="weatherDataContainer" class="grid grid-cols-1 md:grid-cols-4 gap-4">
120
+ <div class="col-span-full text-center text-gray-600">
121
+ Weather data will appear here after you select or update a location.
122
+ </div>
123
+ </div>
124
+ </div>
125
+
126
+ <!-- Soil Data Section -->
127
+ <div class="form-section" id="soilPropertiesTable">
128
+ <h4 class="text-2xl font-semibold mb-4">Soil Nutrient Parameters</h4>
129
+ <div id="soilTableContainer">
130
+ <p class="text-center text-gray-600">Fetching soil data...</p>
131
+ </div>
132
+ </div>
133
+
134
+ <!-- Additional Agricultural Inputs -->
135
+ <div class="form-section">
136
+ <h4 class="text-2xl font-semibold mb-4">Additional Agricultural Inputs</h4>
137
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
138
+ <div>
139
+ <label class="font-medium" for="crop_type">Crop Type:</label>
140
+ <select class="form-control" id="crop_type" name="crop_type">
141
+ <option value="rice">Rice</option>
142
+ <option value="wheat">Wheat</option>
143
+ <option value="maize">Maize</option>
144
+ <option value="cotton">Cotton</option>
145
+ <option value="sugarcane">Sugarcane</option>
146
+ <option value="soybean">Soybean</option>
147
+ <option value="millet">Millet</option>
148
+ <option value="pulses">Pulses</option>
149
+ <option value="potato">Potato</option>
150
+ <option value="tomato">Tomato</option>
151
+ <option value="onion">Onion</option>
152
+ <option value="garlic">Garlic</option>
153
+ <option value="groundnut">Groundnut</option>
154
+ <option value="barley">Barley</option>
155
+ <option value="jute">Jute</option>
156
+ <option value="tea">Tea</option>
157
+ <option value="coffee">Coffee</option>
158
+ <option value="sorghum">Sorghum</option>
159
+ <option value="turmeric">Turmeric</option>
160
+ <option value="ginger">Ginger</option>
161
+ </select>
162
+ </div>
163
+ <div>
164
+ <label class="font-medium" for="sowing_date">Plant Sowing Date:</label>
165
+ <input type="date" class="form-control" id="sowing_date" name="sowing_date" />
166
+ </div>
167
+ <div>
168
+ <label class="font-medium" for="harvest_date">Expected Harvest Date:</label>
169
+ <input type="date" class="form-control" id="harvest_date" name="harvest_date" />
170
+ </div>
171
+ <div>
172
+ <label class="font-medium" for="growth_stage">Current Growth Stage:</label>
173
+ <select class="form-control" id="growth_stage" name="growth_stage">
174
+ <option value="sowing">Sowing</option>
175
+ <option value="germination">Germination</option>
176
+ <option value="vegetative">Vegetative</option>
177
+ <option value="flowering">Flowering</option>
178
+ <option value="fruiting">Fruiting</option>
179
+ <option value="harvest">Harvest</option>
180
+ </select>
181
+ </div>
182
+ <div>
183
+ <label class="font-medium" for="irrigation_freq">Irrigation Frequency:</label>
184
+ <select class="form-control" id="irrigation_freq" name="irrigation_freq">
185
+ <option value="daily">Daily</option>
186
+ <option value="alternate">Alternate Day</option>
187
+ <option value="twice_week">Twice a Week</option>
188
+ <option value="weekly">Weekly</option>
189
+ </select>
190
+ </div>
191
+ <div>
192
+ <label class="font-medium" for="irrigation_method">Irrigation Method:</label>
193
+ <select class="form-control" id="irrigation_method" name="irrigation_method">
194
+ <option value="drip">Drip</option>
195
+ <option value="sprinkler">Sprinkler</option>
196
+ <option value="flood">Flood</option>
197
+ <option value="manual">Manual</option>
198
+ </select>
199
+ </div>
200
+ <div>
201
+ <label class="font-medium" for="soil_type">Soil Type:</label>
202
+ <select class="form-control" id="soil_type" name="soil_type">
203
+ <option value="red">Red</option>
204
+ <option value="black">Black</option>
205
+ <option value="clay">Clay</option>
206
+ <option value="sandy">Sandy</option>
207
+ <option value="loamy">Loamy</option>
208
+ </select>
209
+ </div>
210
+ <div class="mb-4">
211
+ <label for="language" class="form-label">Response Language</label>
212
+ <select class="form-control" id="language" name="language" required>
213
+ <option value="English">English</option>
214
+ <option value="Hindi">Hindi</option>
215
+ <option value="Bengali">Bengali</option>
216
+ <option value="Telugu">Telugu</option>
217
+ <option value="Marathi">Marathi</option>
218
+ <option value="Tamil">Tamil</option>
219
+ <option value="Gujarati">Gujarati</option>
220
+ <option value="Urdu">Urdu</option>
221
+ <option value="Kannada">Kannada</option>
222
+ <option value="Odia">Odia</option>
223
+ <option value="Malayalam">Malayalam</option>
224
+ </select>
225
+ </div>
226
+
227
+ </div>
228
+ </div>
229
+
230
+ <!-- Hidden Fields for passing Weather data to Gemini -->
231
+ <input type="hidden" id="max_temp_hidden" name="max_temp" />
232
+ <input type="hidden" id="min_temp_hidden" name="min_temp" />
233
+ <input type="hidden" id="current_temp_hidden" name="current_temp" />
234
+ <input type="hidden" id="humidity_hidden" name="humidity" />
235
+ <input type="hidden" id="rainfall_hidden" name="rain" />
236
+ <input type="hidden" id="soil_moisture_hidden" name="soil_moisture" />
237
+ <input type="hidden" id="wind_speed_hidden" name="wind_speed" />
238
+ <input type="hidden" id="cloud_cover_hidden" name="cloud_cover" />
239
+
240
+ <div class="form-section text-center">
241
+ <button type="submit" class="btn btn-success btn-lg shadow-xl transform hover:scale-105 transition duration-300">
242
+ Predict Pest Outbreak
243
+ </button>
244
+ </div>
245
+ </form>
246
+ </div>
247
+
248
+ <!-- Scripts -->
249
+ <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
250
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
251
+ <!-- Leaflet JS -->
252
+ <script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
253
+ <!-- Leaflet Control Geocoder JS for search -->
254
+ <script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script>
255
+ <script>
256
+ // Initialize the map using Esri's World Imagery (satellite view)
257
+ var map = L.map('map').setView([20.5937, 78.9629], 5);
258
+ L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', {
259
+ attribution: 'Tiles © Esri',
260
+ maxZoom: 18,
261
+ }).addTo(map);
262
+
263
+ // Explicitly define the geocoder provider using Nominatim
264
+ var geocoder = L.Control.Geocoder.nominatim();
265
+
266
+ // Add geocoder (search bar) to the map with the provider
267
+ L.Control.geocoder({
268
+ geocoder: geocoder,
269
+ defaultMarkGeocode: false
270
+ })
271
+ .on('markgeocode', function(e) {
272
+ var bbox = e.geocode.bbox;
273
+ var center = e.geocode.center;
274
+ map.fitBounds(bbox);
275
+ setMarker(center);
276
+ })
277
+ .addTo(map);
278
+
279
+ var marker;
280
+ function setMarker(latlng) {
281
+ if (marker) {
282
+ marker.setLatLng(latlng);
283
+ } else {
284
+ marker = L.marker(latlng).addTo(map);
285
+ }
286
+ // Update both hidden and manual fields
287
+ document.getElementById('latitude').value = latlng.lat.toFixed(6);
288
+ document.getElementById('longitude').value = latlng.lng.toFixed(6);
289
+ document.getElementById('manual_lat').value = latlng.lat.toFixed(6);
290
+ document.getElementById('manual_lon').value = latlng.lng.toFixed(6);
291
+
292
+ // Fetch weather and soil data
293
+ fetchWeatherData(latlng.lat, latlng.lng);
294
+ fetchSoilProperties(latlng.lat, latlng.lng);
295
+ }
296
+
297
+ map.on('click', function(e) {
298
+ setMarker(e.latlng);
299
+ });
300
+
301
+ // Update location using manual input
302
+ document.getElementById('updateLocationBtn').addEventListener('click', function(){
303
+ const lat = parseFloat(document.getElementById('manual_lat').value);
304
+ const lon = parseFloat(document.getElementById('manual_lon').value);
305
+ if(!isNaN(lat) && !isNaN(lon)){
306
+ const latlng = L.latLng(lat, lon);
307
+ map.setView(latlng, 10);
308
+ setMarker(latlng);
309
+ } else {
310
+ alert("Please enter valid latitude and longitude values.");
311
+ }
312
+ });
313
+
314
+ // Fetch weather data from backend (/get_weather_data)
315
+ function fetchWeatherData(lat, lng) {
316
+ fetch(/get_weather_data?lat=${lat}&lon=${lng})
317
+ .then(response => response.json())
318
+ .then(data => {
319
+ // Update the weather card container
320
+ const container = document.getElementById('weatherDataContainer');
321
+ container.innerHTML = `
322
+ <div class="weather-card">
323
+ <div class="weather-title">Max Temp</div>
324
+ <div>${data.max_temp !== null ? data.max_temp + " °C" : "Not available"}</div>
325
+ </div>
326
+ <div class="weather-card">
327
+ <div class="weather-title">Min Temp</div>
328
+ <div>${data.min_temp !== null ? data.min_temp + " °C" : "Not available"}</div>
329
+ </div>
330
+ <div class="weather-card">
331
+ <div class="weather-title">Current Temp</div>
332
+ <div>${data.current_temp !== null ? data.current_temp + " °C" : "Not available"}</div>
333
+ </div>
334
+ <div class="weather-card">
335
+ <div class="weather-title">Humidity</div>
336
+ <div>${data.humidity !== null ? data.humidity.toFixed(1) + " %" : "Not available"}</div>
337
+ </div>
338
+ <div class="weather-card">
339
+ <div class="weather-title">Rain</div>
340
+ <div>${data.rainfall !== null ? data.rainfall + " mm" : "Not available"}</div>
341
+ </div>
342
+ <div class="weather-card">
343
+ <div class="weather-title">Soil Moisture</div>
344
+ <div>${data.soil_moisture !== null ? data.soil_moisture.toFixed(1) + " %" : "Not available"}</div>
345
+ </div>
346
+ <div class="weather-card">
347
+ <div class="weather-title">Wind Speed</div>
348
+ <div>${data.wind_speed !== null ? data.wind_speed + " km/h" : "Not available"}</div>
349
+ </div>
350
+ <div class="weather-card">
351
+ <div class="weather-title">Cloud Cover</div>
352
+ <div>${data.cloud_cover !== null ? data.cloud_cover.toFixed(1) + " %" : "Not available"}</div>
353
+ </div>
354
+ `;
355
+
356
+ // Also store these values in hidden fields so they pass to Gemini
357
+ document.getElementById('max_temp_hidden').value = data.max_temp ?? "";
358
+ document.getElementById('min_temp_hidden').value = data.min_temp ?? "";
359
+ document.getElementById('current_temp_hidden').value = data.current_temp ?? "";
360
+ document.getElementById('humidity_hidden').value = data.humidity ?? "";
361
+ document.getElementById('rainfall_hidden').value = data.rainfall ?? "";
362
+ document.getElementById('soil_moisture_hidden').value = data.soil_moisture ?? "";
363
+ document.getElementById('wind_speed_hidden').value = data.wind_speed ?? "";
364
+ document.getElementById('cloud_cover_hidden').value = data.cloud_cover ?? "";
365
+ })
366
+ .catch(error => console.error('Error fetching weather data:', error));
367
+ }
368
+
369
+ // Fetch soil properties from backend (/get_soil_properties)
370
+ function fetchSoilProperties(lat, lng) {
371
+ fetch(/get_soil_properties?lat=${lat}&lon=${lng})
372
+ .then(response => response.json())
373
+ .then(data => {
374
+ if(data.soil_properties) {
375
+ let tableHTML = "<table><thead><tr><th>Parameter</th><th>Value</th><th>Unit</th></tr></thead><tbody>";
376
+ data.soil_properties.forEach(function(item) {
377
+ tableHTML += <tr><td>${item[0]}</td><td>${item[1]}</td><td>${item[2]}</td></tr>;
378
+ });
379
+ tableHTML += "</tbody></table>";
380
+ document.getElementById("soilTableContainer").innerHTML = tableHTML;
381
+ } else {
382
+ document.getElementById("soilTableContainer").innerHTML = "<p class='text-center text-gray-600'>No soil data available.</p>";
383
+ }
384
+ })
385
+ .catch(error => console.error('Error fetching soil properties:', error));
386
+ }
387
+ </script>
388
+ </body>
389
+ </html>