Spaces:
Sleeping
Sleeping
{% extends "base.html" %} | |
{% block title %}Farmer Dashboard - Farm Management Portal{% endblock %} | |
{% block content %} | |
<div class="container mt-4"> | |
<!-- Welcome Header --> | |
<div class="row mb-4"> | |
<div class="col-12"> | |
<div class="card bg-success text-white"> | |
<div class="card-body"> | |
<h2><i class="fas fa-tachometer-alt me-2"></i>Welcome, {{ farmer.name }}!</h2> | |
<p class="mb-0">Manage your farms and get AI-powered daily recommendations</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Quick Stats --> | |
<div class="row mb-4"> | |
<div class="col-md-3 mb-3"> | |
<div class="card text-center"> | |
<div class="card-body"> | |
<i class="fas fa-seedling fa-2x text-success mb-2"></i> | |
<h5>{{ farms|length }}</h5> | |
<small class="text-muted">Total Farms</small> | |
</div> | |
</div> | |
</div> | |
<div class="col-md-3 mb-3"> | |
<div class="card text-center"> | |
<div class="card-body"> | |
<i class="fas fa-calendar-check fa-2x text-primary mb-2"></i> | |
<h5>{{ recent_activities|length }}</h5> | |
<small class="text-muted">Recent Activities</small> | |
</div> | |
</div> | |
</div> | |
<div class="col-md-3 mb-3"> | |
<div class="card text-center"> | |
<div class="card-body"> | |
<i class="fas fa-sms fa-2x text-info mb-2"></i> | |
<h5>{% if today_advisory %}Active{% else %}Pending{% endif %}</h5> | |
<small class="text-muted">Today's Advisory</small> | |
</div> | |
</div> | |
</div> | |
<div class="col-md-3 mb-3"> | |
<div class="card text-center"> | |
<div class="card-body"> | |
<i class="fas fa-user fa-2x text-warning mb-2"></i> | |
<h5>{{ farmer.contact_number }}</h5> | |
<small class="text-muted">Contact</small> | |
</div> | |
</div> | |
</div> | |
</div> | |
<div class="row"> | |
<!-- Today's Advisory --> | |
<div class="col-md-8 mb-4"> | |
<div class="card"> | |
<div class="card-header bg-primary text-white"> | |
<h5><i class="fas fa-brain me-2"></i>Today's AI Advisory</h5> | |
</div> | |
<div class="card-body"> | |
{% if today_advisory %} | |
<div class="alert alert-success"> | |
<h6><i class="fas fa-check-circle me-2"></i>Tasks to Do:</h6> | |
<p>{{ today_advisory.task_to_do }}</p> | |
</div> | |
<div class="alert alert-warning"> | |
<h6><i class="fas fa-exclamation-triangle me-2"></i>Tasks to Avoid:</h6> | |
<p>{{ today_advisory.task_to_avoid }}</p> | |
</div> | |
{% if today_advisory.reason_explanation %} | |
<div class="alert alert-info"> | |
<h6><i class="fas fa-info-circle me-2"></i>Explanation:</h6> | |
<p>{{ today_advisory.reason_explanation }}</p> | |
</div> | |
{% endif %} | |
{% if farms %} | |
<div class="mt-3"> | |
<button class="btn btn-success" onclick="sendSMSAdvisory({{ farms[0].id }})"> | |
<i class="fas fa-sms me-2"></i>Send SMS Alert | |
</button> | |
<button class="btn btn-primary" onclick="generateNewAdvisory({{ farms[0].id }})"> | |
<i class="fas fa-sync me-2"></i>Refresh Advisory | |
</button> | |
</div> | |
{% endif %} | |
{% else %} | |
<div class="text-center text-muted py-4"> | |
<i class="fas fa-robot fa-3x mb-3"></i> | |
<h6>No advisory generated yet for today</h6> | |
<p>Click below to generate AI-powered recommendations</p> | |
{% if farms %} | |
<button class="btn btn-primary" onclick="generateNewAdvisory({{ farms[0].id }})"> | |
<i class="fas fa-magic me-2"></i>Generate Advisory | |
</button> | |
{% endif %} | |
</div> | |
{% endif %} | |
</div> | |
</div> | |
</div> | |
<!-- Quick Actions --> | |
<div class="col-md-4 mb-4"> | |
<div class="card"> | |
<div class="card-header bg-secondary text-white"> | |
<h5><i class="fas fa-bolt me-2"></i>Quick Actions</h5> | |
</div> | |
<div class="card-body"> | |
<div class="d-grid gap-2"> | |
<a href="{{ url_for('add_farm') }}" class="btn btn-success"> | |
<i class="fas fa-plus me-2"></i>Add New Farm | |
</a> | |
{% if farms %} | |
<a href="{{ url_for('farm_details', farm_id=farms[0].id) }}" class="btn btn-primary"> | |
<i class="fas fa-eye me-2"></i>View Farm Details | |
</a> | |
<button class="btn btn-info" onclick="checkWeather({{ farms[0].id }})"> | |
<i class="fas fa-cloud me-2"></i>Check Weather | |
</button> | |
{% endif %} | |
<a href="{{ url_for('farmer_logout') }}" class="btn btn-outline-danger"> | |
<i class="fas fa-sign-out-alt me-2"></i>Logout | |
</a> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
<!-- Farms List --> | |
{% if farms %} | |
<div class="row mb-4"> | |
<div class="col-12"> | |
<div class="card"> | |
<div class="card-header"> | |
<h5><i class="fas fa-list me-2"></i>Your Farms</h5> | |
</div> | |
<div class="card-body"> | |
<div class="table-responsive"> | |
<table class="table table-striped"> | |
<thead> | |
<tr> | |
<th>Farm Name</th> | |
<th>Size (Acres)</th> | |
<th>Crops</th> | |
<th>Irrigation</th> | |
<th>Actions</th> | |
</tr> | |
</thead> | |
<tbody> | |
{% for farm in farms %} | |
<tr> | |
<td>{{ farm.farm_name }}</td> | |
<td>{{ farm.farm_size }}</td> | |
<td> | |
{% for crop in farm.get_crop_types() %} | |
<span class="badge bg-success me-1">{{ crop }}</span> | |
{% endfor %} | |
</td> | |
<td>{{ farm.irrigation_type }}</td> | |
<td> | |
<a href="{{ url_for('farm_details', farm_id=farm.id) }}" class="btn btn-sm btn-primary"> | |
<i class="fas fa-eye"></i> | |
</a> | |
<button class="btn btn-sm btn-success" onclick="generateNewAdvisory({{ farm.id }})"> | |
<i class="fas fa-brain"></i> | |
</button> | |
</td> | |
</tr> | |
{% endfor %} | |
</tbody> | |
</table> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endif %} | |
<!-- Recent Activities --> | |
{% if recent_activities %} | |
<div class="row"> | |
<div class="col-12"> | |
<div class="card"> | |
<div class="card-header"> | |
<h5><i class="fas fa-history me-2"></i>Recent Activities</h5> | |
</div> | |
<div class="card-body"> | |
<div class="timeline"> | |
{% for activity in recent_activities %} | |
<div class="timeline-item mb-3"> | |
<div class="d-flex"> | |
<div class="flex-shrink-0"> | |
<i class="fas fa-circle text-success"></i> | |
</div> | |
<div class="flex-grow-1 ms-3"> | |
<h6 class="mb-1">{{ activity.activity_type|title }}</h6> | |
<p class="mb-1">{{ activity.activity_description }}</p> | |
<small class="text-muted"> | |
Scheduled: {{ activity.scheduled_date.strftime('%d %b %Y') }} | |
| Status: <span class="badge bg-{{ 'success' if activity.status == 'completed' else 'warning' }}">{{ activity.status|title }}</span> | |
</small> | |
</div> | |
</div> | |
</div> | |
{% endfor %} | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endif %} | |
</div> | |
<!-- Loading Modal --> | |
<div class="modal fade" id="loadingModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"> | |
<div class="modal-dialog modal-dialog-centered"> | |
<div class="modal-content"> | |
<div class="modal-body text-center"> | |
<div class="spinner-border text-primary" role="status"> | |
<span class="visually-hidden">Loading...</span> | |
</div> | |
<p class="mt-3 mb-0">Processing your request...</p> | |
</div> | |
</div> | |
</div> | |
</div> | |
{% endblock %} | |
{% block extra_js %} | |
<script> | |
// Helper to show/hide the Bootstrap 5 modal using vanilla JS | |
function _getLoadingModalInstance(){ | |
const modalEl = document.getElementById('loadingModal'); | |
return bootstrap.Modal.getOrCreateInstance(modalEl); | |
} | |
function generateNewAdvisory(farmId) { | |
const modal = _getLoadingModalInstance(); | |
modal.show(); | |
fetch(`/generate_advisory/${farmId}`) | |
.then(response => response.json()) | |
.then(data => { | |
modal.hide(); | |
if (data.success) { | |
// Reload to show updated advisory | |
location.reload(); | |
} else { | |
alert('Failed to generate advisory: ' + (data.error || 'Unknown error')); | |
} | |
}) | |
.catch(error => { | |
modal.hide(); | |
alert('Error: ' + error.message); | |
}); | |
} | |
function sendSMSAdvisory(farmId) { | |
const modal = _getLoadingModalInstance(); | |
modal.show(); | |
fetch(`/send_sms_advisory/${farmId}`) | |
.then(response => response.json()) | |
.then(data => { | |
modal.hide(); | |
if (data.success) { | |
alert('SMS sent successfully!'); | |
} else { | |
alert('Failed to send SMS: ' + (data.error || 'Unknown error')); | |
} | |
}) | |
.catch(error => { | |
modal.hide(); | |
alert('Error: ' + error.message); | |
}); | |
} | |
function checkWeather(farmId) { | |
const modal = _getLoadingModalInstance(); | |
modal.show(); | |
fetch(`/api/weather/${farmId}`) | |
.then(response => response.json()) | |
.then(data => { | |
modal.hide(); | |
if (data.error) { | |
alert('Weather data unavailable: ' + data.error); | |
} else { | |
let weatherInfo = `Current Weather:\n`; | |
weatherInfo += `Temperature: ${data.main?.temp || 'N/A'}°C\n`; | |
weatherInfo += `Humidity: ${data.main?.humidity || 'N/A'}%\n`; | |
weatherInfo += `Condition: ${data.weather?.[0]?.description || 'N/A'}\n`; | |
weatherInfo += `Wind: ${data.wind?.speed ? (data.wind.speed * 3.6).toFixed(1) : 'N/A'} km/h\n`; | |
alert(weatherInfo); | |
} | |
}) | |
.catch(error => { | |
modal.hide(); | |
alert('Error: ' + error.message); | |
}); | |
} | |
</script> | |
{% endblock %} | |