RushiMane2003's picture
Update templates/predict.html
4210945 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Prediction Results</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background-color: #f4f8f4;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
.header {
background-color: #28a745;
color: white;
padding: 20px;
text-align: center;
font-weight: bold;
}
.container {
margin-top: 30px;
padding: 20px;
background-color: white;
border-radius: 15px;
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
opacity: 0;
transition: opacity 0.5s ease-in-out;
}
.result-label {
font-weight: bold;
color: #555;
}
.form-control[readonly] {
font-size: 1.2rem;
text-align: center;
font-weight: bold;
color: #28a745;
background-color: #e9f5e9;
border: 2px solid #28a745;
}
.gauge-container {
margin-top: 20px;
text-align: center;
}
.info-card {
background-color: #f8f9fa;
border: 1px solid #dee2e6;
border-radius: 10px;
padding: 25px;
margin-top: 40px;
text-align: center;
}
.btn-start-motor {
background-color: #28a745;
color: white;
font-size: 1.2rem;
padding: 12px 25px;
font-weight: bold;
border-radius: 8px;
transition: background-color 0.3s;
}
.btn-start-motor:hover {
background-color: #218838;
}
.camera-container {
margin-top: 20px;
display: none;
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
video {
width: 100%;
max-width: 720px;
height: auto;
border-radius: 10px;
border: 2px solid #ddd;
background-color: #000;
}
.timer {
font-size: 2rem;
color: white;
background-color: #28a745;
font-weight: bold;
padding: 10px 25px;
border-radius: 10px;
display: inline-block;
min-width: 120px;
text-align: center;
}
.timer-finished {
font-size: 1.5rem;
padding: 15px 40px;
background-color: #28a745;
}
.alert-message {
font-size: 1.5rem;
color: #dc3545;
font-weight: bold;
margin-top: 20px;
text-align: center;
}
/* Modal small style tweak */
.modal-header {
background-color: #28a745;
color: white;
}
</style>
</head>
<body>
<div class="header">
<h1>Water Requirement Prediction Results</h1>
</div>
<div class="container">
<div class="row">
<!-- Water Requirement -->
<div class="col-md-6 mb-4">
<label for="water_requirement" class="result-label">Predicted Water Requirement (mΒ³/sq.m):</label>
<input type="text" class="form-control" id="water_requirement" value="{{ water_requirement }}" readonly>
<div class="gauge-container">
{{ water_gauge|safe }}
</div>
</div>
<!-- Motor On Time -->
<div class="col-md-6 mb-4">
<label for="estimated_time" class="result-label">Estimated Motor On-Time:</label>
<input type="text" class="form-control" id="estimated_time" value="{{ estimated_time_duration }} {{ time_unit }}" readonly>
<div class="gauge-container">
{{ time_gauge|safe }}
</div>
</div>
</div>
<!-- AI Monitoring Section -->
<div class="info-card">
<h4>Want to automatically inspect your irrigation process?</h4>
<p class="mt-3">Use our AI-driven Irrigation Monitoring to watch the process from your phone. You will receive a WhatsApp message to start the motor. Once started, you can monitor it live here.</p>
<button id="startMonitoring" class="btn btn-start-motor">Start AI Monitoring</button>
</div>
<!-- The camera and timer -->
<div class="camera-container" id="cameraContainer">
<h4 class="text-center mb-0">Live Irrigation Feed</h4>
<video id="videoElement" autoplay playsinline></video>
<div class="timer" id="timer"></div>
</div>
<div class="alert-message" id="alertMessage"></div>
</div>
<!-- --- START: Modal asking 1 or 0 --- -->
<div class="modal fade" id="startModal" tabindex="-1" aria-labelledby="startModalLabel" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="startModalLabel">Start Irrigation</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<p>Would you like to start the motor now?</p>
<p class="mb-0"><strong>Reply 1</strong> = Start &nbsp;&nbsp; <strong>Reply 0</strong> = Cancel</p>
</div>
<div class="modal-footer">
<button id="modalCancelBtn" type="button" class="btn btn-secondary" data-bs-dismiss="modal">0 β€” Don't Start</button>
<button id="modalStartBtn" type="button" class="btn btn-success">1 β€” Start</button>
</div>
</div>
</div>
</div>
<!-- --- END: Modal --- -->
<!-- Bootstrap bundle (includes Popper) -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Fade in container
window.onload = function() {
document.querySelector('.container').style.opacity = 1;
// Show the modal automatically on load
var startModalEl = document.getElementById('startModal');
var bsModal = new bootstrap.Modal(startModalEl, { backdrop: 'static', keyboard: false });
bsModal.show();
// Button handlers for modal
document.getElementById('modalStartBtn').addEventListener('click', function() {
bsModal.hide();
// Programmatically click the Start Monitoring button so existing logic executes (camera + client timer + server POST)
document.getElementById('startMonitoring').click();
});
document.getElementById('modalCancelBtn').addEventListener('click', function() {
// User chose "0" - do not start monitoring
bsModal.hide();
document.getElementById('alertMessage').textContent = "Motor was not started.";
});
};
document.getElementById('startMonitoring').addEventListener('click', function() {
document.getElementById('cameraContainer').style.display = 'flex';
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
navigator.mediaDevices.getUserMedia({ video: { facingMode: 'environment' } })
.then(function(stream) {
document.getElementById('videoElement').srcObject = stream;
})
.catch(function(err) {
console.log("Camera Error: " + err);
alert("Could not access the camera. Please ensure you have given permission.");
});
}
let estimatedTime = parseFloat("{{ estimated_time_duration }}");
let timeUnit = "{{ time_unit }}";
let estimatedTimeSeconds = timeUnit === "minutes" ? estimatedTime * 60 : estimatedTime;
let timerElem = document.getElementById('timer');
let timeRemaining = Math.floor(estimatedTimeSeconds);
// Note: start_motor fetch is already below. We keep it so server-side timer + completion messages work.
let countdown = setInterval(function() {
if (timeRemaining <= 0) {
clearInterval(countdown);
timerElem.textContent = "Finished";
timerElem.classList.add('timer-finished');
let beep = new Audio('/static/alarn_tune.mp3');
beep.play();
document.getElementById('alertMessage').textContent = "Irrigation time is over. Motor is off automatically.";
} else {
timerElem.textContent = timeRemaining + "s";
}
timeRemaining--;
}, 1000);
// Call the server endpoint which now starts the server-side timer (so finalization/WhatsApp behavior remains consistent)
fetch('/start_motor', { method: 'POST' })
.then(response => response.json())
.then(data => {
console.log("Monitoring request sent:", data);
if (data && data.status === "motor_started") {
// optionally show a confirmation to user
document.getElementById('alertMessage').textContent = `Motor started for ${data.estimated_time_duration} ${data.time_unit}.`;
} else {
if (data && data.status === "no_pending_task") {
document.getElementById('alertMessage').textContent = "No pending irrigation task found. Please submit a new prediction.";
}
}
})
.catch(error => {
console.error("Error sending monitoring request:", error);
document.getElementById('alertMessage').textContent = "Error starting motor on server. Check logs.";
});
});
</script>
</body>
</html>