let the year be changeable

This commit is contained in:
NABU Jena 2025-07-09 08:29:06 +02:00
parent 1368217187
commit e047dade4d
2 changed files with 121 additions and 12 deletions

View file

@ -281,6 +281,27 @@
height: 20px;
border-radius: 4px;
}
/* Jahr-Navigation */
.year-navigation .btn {
border-radius: 50%;
width: 40px;
height: 40px;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.3s ease;
}
.year-navigation .btn:hover:not(:disabled) {
background-color: rgba(255, 255, 255, 0.2);
transform: scale(1.1);
}
.year-navigation .btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
</style>
{% endblock %}
@ -295,11 +316,40 @@
</div>
</div>
<!-- 1. Übersicht aktuelles Jahr -->
<div class="section-header">
<!-- 1. Übersicht ausgewähltes Jahr mit Navigation -->
<div class="section-header d-flex justify-content-between align-items-center">
<h2 class="mb-0">
<i class="fas fa-calendar-alt"></i> Übersicht {{ current_year }}
<i class="fas fa-calendar-alt"></i> Übersicht {{ selected_year }}
</h2>
<div class="year-navigation d-flex align-items-center">
{% if can_go_previous %}
<a href="?year={{ previous_year }}" class="btn btn-outline-light me-2" title="Vorheriges Jahr ({{ previous_year }})">
<i class="fas fa-chevron-left"></i>
</a>
{% else %}
<button class="btn btn-outline-light me-2" disabled title="Keine Daten vor {{ earliest_year }}">
<i class="fas fa-chevron-left"></i>
</button>
{% endif %}
<span class="mx-3 fw-bold">{{ selected_year }}</span>
{% if can_go_next %}
<a href="?year={{ next_year }}" class="btn btn-outline-light ms-2" title="Nächstes Jahr ({{ next_year }})">
<i class="fas fa-chevron-right"></i>
</a>
{% else %}
<button class="btn btn-outline-light ms-2" disabled title="Aktuelles Jahr erreicht">
<i class="fas fa-chevron-right"></i>
</button>
{% endif %}
{% if selected_year != current_year %}
<a href="?year={{ current_year }}" class="btn btn-light ms-3" title="Zurück zu {{ current_year }}">
<i class="fas fa-calendar-day me-1"></i>{{ current_year }}
</a>
{% endif %}
</div>
</div>
<div class="row g-4 mb-4">
@ -441,7 +491,7 @@
<div class="col-md-6">
<div class="card">
<div class="card-header">
<h5 class="mb-0">{{ current_year }}</h5>
<h5 class="mb-0">{{ selected_year }}</h5>
</div>
<div class="card-body">
{% if circumstances_this_year %}
@ -456,7 +506,7 @@
</div>
{% else %}
<div class="text-center text-muted">
<p>Keine Daten für {{ current_year }} verfügbar</p>
<p>Keine Daten für {{ selected_year }} verfügbar</p>
</div>
{% endif %}
</div>
@ -516,6 +566,37 @@ document.addEventListener('DOMContentLoaded', function() {
}
}
});
// Tastatur-Navigation für Jahre
document.addEventListener('keydown', function(e) {
// Nur reagieren wenn kein Input-Element fokussiert ist
if (document.activeElement.tagName === 'INPUT' || document.activeElement.tagName === 'TEXTAREA') {
return;
}
if (e.key === 'ArrowLeft') {
// Vorheriges Jahr
const prevButton = document.querySelector('a[href*="year={{ previous_year }}"]');
if (prevButton) {
window.location.href = prevButton.href;
}
} else if (e.key === 'ArrowRight') {
// Nächstes Jahr
const nextButton = document.querySelector('a[href*="year={{ next_year }}"]');
if (nextButton) {
window.location.href = nextButton.href;
}
} else if (e.key === 'Home') {
// Zurück zum aktuellen Jahr
const currentYearButton = document.querySelector('a[href*="year={{ current_year }}"]');
if (currentYearButton) {
window.location.href = currentYearButton.href;
} else {
// Falls schon im aktuellen Jahr, zur Statistik-Hauptseite
window.location.href = window.location.pathname;
}
}
});
});
</script>
{% endblock %}

View file

@ -1,6 +1,6 @@
from django.views.generic import TemplateView
from django.contrib.auth.mixins import LoginRequiredMixin
from django.db.models import Count, Q
from django.db.models import Count, Q, Min
from django.utils import timezone
from datetime import datetime
from bird.models import FallenBird, Bird, BirdStatus, Circumstance
@ -13,9 +13,31 @@ class StatisticView(LoginRequiredMixin, TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
# Aktuelles Jahr
# Jahr aus URL-Parameter oder aktuelles Jahr
selected_year = self.request.GET.get('year', timezone.now().year)
try:
selected_year = int(selected_year)
except (ValueError, TypeError):
selected_year = timezone.now().year
current_year = timezone.now().year
# Stelle sicher, dass das ausgewählte Jahr nicht in der Zukunft liegt
if selected_year > current_year:
selected_year = current_year
# Finde das früheste Jahr mit Daten
earliest_year_with_data = FallenBird.objects.aggregate(
earliest=Min('date_found__year')
)['earliest']
if earliest_year_with_data is None:
earliest_year_with_data = current_year
# Stelle sicher, dass das ausgewählte Jahr nicht vor dem frühesten Jahr liegt
if selected_year < earliest_year_with_data:
selected_year = earliest_year_with_data
# Lade aktive Konfiguration
try:
config = StatisticConfiguration.objects.get(is_active=True)
@ -31,11 +53,17 @@ class StatisticView(LoginRequiredMixin, TemplateView):
context['config'] = config
context['current_year'] = current_year
context['selected_year'] = selected_year
context['earliest_year'] = earliest_year_with_data
context['can_go_previous'] = selected_year > earliest_year_with_data
context['can_go_next'] = selected_year < current_year
context['previous_year'] = selected_year - 1 if context['can_go_previous'] else None
context['next_year'] = selected_year + 1 if context['can_go_next'] else None
# 1. Jahresstatistik
if config.show_year_total_patients:
patients_this_year = FallenBird.objects.filter(
date_found__year=current_year
date_found__year=selected_year
).count()
context['patients_this_year'] = patients_this_year
@ -46,7 +74,7 @@ class StatisticView(LoginRequiredMixin, TemplateView):
for group in year_groups:
status_ids = list(group.status_list.values_list('id', flat=True))
year_count = FallenBird.objects.filter(
date_found__year=current_year,
date_found__year=selected_year,
status__id__in=status_ids
).count()
@ -144,10 +172,10 @@ class StatisticView(LoginRequiredMixin, TemplateView):
context['bird_stats'] = bird_stats
# 4. Fundumstände-Statistiken (unverändert)
# Fundumstände für aktuelles Jahr
# 4. Fundumstände-Statistiken
# Fundumstände für ausgewähltes Jahr
circumstances_this_year = FallenBird.objects.filter(
date_found__year=current_year,
date_found__year=selected_year,
find_circumstances__isnull=False
).values('find_circumstances__name', 'find_circumstances__description').annotate(
count=Count('id')