Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>Pest Outbreak Prediction</title> | |
| <!-- Fonts --> | |
| <link href="https://fonts.googleapis.com/css2?family=Outfit:wght@300;400;500;600;700&display=swap" rel="stylesheet"> | |
| <!-- Bootstrap 5 --> | |
| <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"> | |
| <!-- Icons --> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css"> | |
| <!-- Leaflet --> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" /> | |
| <link rel="stylesheet" href="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.css" /> | |
| <style> | |
| :root { | |
| --primary-green: #1a5d3a; | |
| --accent-green: #198754; | |
| --light-bg: #f3f4f6; | |
| --glass-white: rgba(255, 255, 255, 0.95); | |
| } | |
| body { | |
| font-family: 'Outfit', sans-serif; | |
| background-color: var(--light-bg); | |
| color: #1f2937; | |
| padding-bottom: 3rem; | |
| } | |
| /* --- Header --- */ | |
| .header-section { | |
| background-color: var(--primary-green); | |
| color: white; | |
| padding: 3rem 1rem 6rem; | |
| text-align: center; | |
| border-bottom-left-radius: 50% 20px; | |
| border-bottom-right-radius: 50% 20px; | |
| margin-bottom: -4rem; | |
| } | |
| .main-container { | |
| max-width: 900px; | |
| /* Reduced width for focus */ | |
| margin: 0 auto; | |
| padding: 0 1rem; | |
| } | |
| /* --- Focused Card --- */ | |
| .dashboard-card { | |
| background: white; | |
| border-radius: 20px; | |
| box-shadow: 0 10px 40px rgba(0, 0, 0, 0.08); | |
| padding: 2.5rem; | |
| border: 1px solid rgba(0, 0, 0, 0.04); | |
| position: relative; | |
| } | |
| .section-label { | |
| font-size: 0.75rem; | |
| text-transform: uppercase; | |
| letter-spacing: 1px; | |
| font-weight: 700; | |
| color: var(--accent-green); | |
| margin-bottom: 1rem; | |
| display: block; | |
| border-bottom: 2px solid #f3f4f6; | |
| padding-bottom: 0.5rem; | |
| } | |
| /* --- Map --- */ | |
| .map-wrapper { | |
| border-radius: 12px; | |
| overflow: hidden; | |
| height: 250px; | |
| margin-bottom: 1.5rem; | |
| box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.1); | |
| position: relative; | |
| } | |
| #map { | |
| height: 100%; | |
| width: 100%; | |
| } | |
| /* --- Inputs --- */ | |
| .form-label { | |
| font-size: 0.9rem; | |
| font-weight: 600; | |
| color: #4b5563; | |
| margin-bottom: 0.4rem; | |
| } | |
| .form-select, | |
| .form-control { | |
| border-radius: 10px; | |
| padding: 0.75rem 1rem; | |
| border: 1px solid #e5e7eb; | |
| font-size: 1rem; | |
| transition: 0.2s; | |
| background-color: #f9fafb; | |
| } | |
| .form-select:focus, | |
| .form-control:focus { | |
| background-color: white; | |
| border-color: var(--accent-green); | |
| box-shadow: 0 0 0 4px rgba(25, 135, 84, 0.1); | |
| } | |
| .btn-predict { | |
| background: linear-gradient(135deg, #1a5d3a 0%, #15803d 100%); | |
| color: white; | |
| font-size: 1.2rem; | |
| font-weight: 700; | |
| padding: 1rem 3rem; | |
| border-radius: 50px; | |
| border: none; | |
| width: 100%; | |
| margin-top: 2rem; | |
| box-shadow: 0 10px 25px rgba(26, 93, 58, 0.25); | |
| transition: 0.3s; | |
| } | |
| .btn-predict:hover { | |
| transform: translateY(-3px); | |
| box-shadow: 0 15px 35px rgba(26, 93, 58, 0.35); | |
| } | |
| /* Loaders */ | |
| #loaderOverlay { | |
| position: fixed; | |
| inset: 0; | |
| background: rgba(255, 255, 255, 0.92); | |
| backdrop-filter: blur(5px); | |
| z-index: 9999; | |
| display: none; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="header-section"> | |
| <h1 class="fw-bold display-5 mb-2">Pest Outbreak Prediction</h1> | |
| <p class="opacity-75 fs-5">AI-Powered Crop Intelligence</p> | |
| </div> | |
| <form id="farmForm" action="/predict" method="post" class="main-container"> | |
| <div class="dashboard-card"> | |
| <!-- 1. Location --> | |
| <span class="section-label">01. Field Location</span> | |
| <div class="row g-3 mb-4"> | |
| <div class="col-lg-8"> | |
| <div class="map-wrapper"> | |
| <div id="map"></div> | |
| </div> | |
| </div> | |
| <div class="col-lg-4 d-flex flex-column justify-content-center"> | |
| <button type="button" id="fetchCurrentLocationBtn" | |
| class="btn btn-outline-success fw-bold mb-3 w-100"> | |
| <i class="bi bi-crosshair me-2"></i> Use GPS Location | |
| </button> | |
| <div class="form-floating mb-2"> | |
| <input type="text" class="form-control" id="manual_lat" placeholder="Lat" readonly> | |
| <label>Latitude</label> | |
| </div> | |
| <div class="form-floating"> | |
| <input type="text" class="form-control" id="manual_lon" placeholder="Lon" readonly> | |
| <label>Longitude</label> | |
| </div> | |
| </div> | |
| <!-- Hidden inputs for form submission --> | |
| <input type="hidden" id="latitude" name="latitude"> | |
| <input type="hidden" id="longitude" name="longitude"> | |
| <!-- Weather hidden fields (populated dynamically if needed, or backend handles it) --> | |
| <input type="hidden" id="max_temp_hidden" name="max_temp"> | |
| <input type="hidden" id="min_temp_hidden" name="min_temp"> | |
| <input type="hidden" id="current_temp_hidden" name="current_temp"> | |
| <input type="hidden" id="humidity_hidden" name="humidity"> | |
| <input type="hidden" id="rainfall_hidden" name="rain"> | |
| <input type="hidden" id="soil_moisture_hidden" name="soil_moisture"> | |
| <input type="hidden" id="wind_speed_hidden" name="wind_speed"> | |
| <input type="hidden" id="cloud_cover_hidden" name="cloud_cover"> | |
| </div> | |
| <!-- 2. Crop Details --> | |
| <span class="section-label">02. Crop Profile</span> | |
| <div class="row g-3 mb-4"> | |
| <div class="col-md-6"> | |
| <label class="form-label">Crop Type</label> | |
| <select class="form-select" id="crop_type" name="crop_type" required> | |
| <option value="" selected disabled>Select Crop...</option> | |
| <option value="Rice (Paddy)">Rice (Paddy)</option> | |
| <option value="Wheat">Wheat</option> | |
| <option value="Maize">Maize (Corn)</option> | |
| <option value="Cotton">Cotton</option> | |
| <option value="Sugarcane">Sugarcane</option> | |
| <option value="Soybean">Soybean</option> | |
| <option value="Tomato">Tomato</option> | |
| <option value="Potato">Potato</option> | |
| <option value="Onion">Onion</option> | |
| <option value="Tea">Tea</option> | |
| <option value="Coffee">Coffee</option> | |
| </select> | |
| </div> | |
| <div class="col-md-6"> | |
| <label class="form-label">Soil Type</label> | |
| <select class="form-select" id="soil_type" name="soil_type" required> | |
| <option value="Black Soil">Black Soil</option> | |
| <option value="Red Soil">Red Soil</option> | |
| <option value="Loamy Soil">Loamy Soil</option> | |
| <option value="Sandy Soil">Sandy Soil</option> | |
| <option value="Clay Soil">Clay Soil</option> | |
| </select> | |
| </div> | |
| </div> | |
| <!-- 3. Smart Season Selection --> | |
| <span class="section-label">03. Cropping Season</span> | |
| <div class="row g-3 mb-4"> | |
| <div class="col-md-6"> | |
| <label class="form-label">Select Season</label> | |
| <div class="input-group"> | |
| <span class="input-group-text bg-light"><i class="bi bi-calendar-range"></i></span> | |
| <select class="form-select" id="season" name="season" required> | |
| <option value="Kharif" selected>Kharif (Monsoon | June - Oct)</option> | |
| <option value="Rabi">Rabi (Winter | Nov - April)</option> | |
| <option value="Zaid">Zaid (Summer | March - June)</option> | |
| <option value="Annual">Annual / Perennial</option> | |
| </select> | |
| </div> | |
| </div> | |
| <div class="col-md-6"> | |
| <label class="form-label">Report Language</label> | |
| <select class="form-select" id="language" name="language"> | |
| <option value="English">English</option> | |
| <option value="Hindi">Hindi</option> | |
| <option value="Marathi">Marathi</option> | |
| <option value="Bengali">Bengali</option> | |
| <option value="Telugu">Telugu</option> | |
| <option value="Tamil">Tamil</option> | |
| <option value="Gujarati">Gujarati</option> | |
| <option value="Kannada">Kannada</option> | |
| </select> | |
| </div> | |
| </div> | |
| <button type="submit" class="btn-predict"> | |
| ANALYZE CROP RISK <i class="bi bi-stars ms-2"></i> | |
| </button> | |
| <div class="text-center mt-3 text-muted small"> | |
| Powered by Gemini 2.0 Flash • Open-Meteo Historical Data | |
| </div> | |
| </div> | |
| </form> | |
| <!-- Loader --> | |
| <div id="loaderOverlay"> | |
| <div class="spinner-border text-success mb-3" style="width: 3rem; height: 3rem;"></div> | |
| <h4 class="fw-bold text-success">Analyzing Field Data...</h4> | |
| <p class="text-muted">Fetching historical climate patterns & predicting risks</p> | |
| </div> | |
| <!-- Scripts --> | |
| <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script> | |
| <script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"></script> | |
| <script src="https://unpkg.com/leaflet-control-geocoder/dist/Control.Geocoder.js"></script> | |
| <script> | |
| // --- Map Init --- | |
| var map = L.map('map').setView([20.5937, 78.9629], 5); | |
| L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}', { | |
| attribution: 'Tiles © Esri' | |
| }).addTo(map); | |
| var marker; | |
| function setMarker(latlng) { | |
| if (marker) marker.setLatLng(latlng); | |
| else marker = L.marker(latlng).addTo(map); | |
| const lat = latlng.lat.toFixed(6); | |
| const lng = latlng.lng.toFixed(6); | |
| // Set hidden and visible inputs | |
| document.getElementById('latitude').value = lat; | |
| document.getElementById('longitude').value = lng; | |
| document.getElementById('manual_lat').value = lat; | |
| document.getElementById('manual_lon').value = lng; | |
| } | |
| map.on('click', function (e) { setMarker(e.latlng); }); | |
| // --- Geolocation --- | |
| document.getElementById('fetchCurrentLocationBtn').addEventListener('click', () => { | |
| if (navigator.geolocation) { | |
| navigator.geolocation.getCurrentPosition(position => { | |
| const latlng = { | |
| lat: position.coords.latitude, | |
| lng: position.coords.longitude | |
| }; | |
| map.setView(latlng, 12); | |
| setMarker(latlng); | |
| }, () => { | |
| alert("Location access denied or unavailable."); | |
| }); | |
| } | |
| }); | |
| // --- Form Submit Animation --- | |
| document.getElementById('farmForm').addEventListener('submit', function (e) { | |
| const lat = document.getElementById('latitude').value; | |
| if (!lat) { | |
| e.preventDefault(); | |
| alert("Please pin a location on the map first!"); | |
| return; | |
| } | |
| document.getElementById('loaderOverlay').style.display = 'flex'; | |
| }); | |
| // --- Init Default Date (Optional) --- | |
| // Sets today as default sowing date for convenience | |
| document.getElementById('sowing_date').valueAsDate = new Date(); | |
| </script> | |
| </body> | |
| </html> |