Add pagination for past events

This commit is contained in:
2026-07-03 14:59:07 +02:00
parent 0571b9fdd9
commit 2e5ac73bf2
3 changed files with 62 additions and 11 deletions

View File

@@ -12,7 +12,7 @@ from fastapi.responses import FileResponse, RedirectResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from pydantic import BaseModel, BeforeValidator, validator
from sqlalchemy import create_engine, select
from sqlalchemy import create_engine, func, select
from sqlalchemy.orm import Session
from meal_manager.grist import sync_with_grist
@@ -93,12 +93,13 @@ SessionDep = Annotated[Session, Depends(get_session)]
UserDep = Annotated[dict, Depends(get_user)]
StrictUserDep = Annotated[dict, Depends(partial(get_user, allow_none=False))]
PAGE_SIZE = 18
@app.get("/")
async def index(request: Request, session: SessionDep, user: UserDep):
"""Displays coming events and a button to register new ones"""
now = datetime.now()
# TODO: Once we refactored to use SQLAlchemy directly, we can probably do a nicer filtering on the date alone
statement = (
select(Event)
.order_by(Event.event_time)
@@ -108,7 +109,14 @@ async def index(request: Request, session: SessionDep, user: UserDep):
return templates.TemplateResponse(
request=request,
name="index.html",
context={"events": events, "current_page": "home", "now": now, "user": user},
context={
"now": now,
"total_pages": 1,
"page": {
"page_number": 1,
"events": events,
},
},
)
@@ -117,20 +125,39 @@ async def robots_txt():
return FileResponse("src/meal_manager/static/robots.txt", media_type="text/plain")
@app.get("/past_events")
async def past_events(request: Request, session: SessionDep):
@app.get("/past_events/{page_number}")
async def past_events(request: Request, session: SessionDep, page_number: int):
now = datetime.now()
# TODO: Once we refactored to use SQLAlchemy directly, we can probably do a nicer filtering on the date alone
statement = (
select(Event)
.order_by(Event.event_time)
.where(Event.event_time < now - timedelta(days=1))
.order_by(Event.event_time.desc())
.offset((page_number - 1) * PAGE_SIZE)
.limit(PAGE_SIZE)
)
events = session.scalars(statement)
num_past_events = (
session.query(func.count(Event.id))
.where(Event.event_time < func.datetime("now", "-1 day"))
.scalar()
)
assert num_past_events is not None, "num_past_events should not be None"
total_pages = num_past_events // PAGE_SIZE + 1
return templates.TemplateResponse(
request=request,
name="index.html",
context={"events": events, "current_page": "past", "now": now},
context={
"now": now,
"total_pages": total_pages,
"page": {
"page_number": page_number,
"events": events,
},
},
)

View File

@@ -25,7 +25,7 @@
<a class="nav-link {% if current_page == 'home' %}active{% endif %}" {% if current_page == 'home' %}aria-current="page"{% endif %} href="/">Kommende</a>
</li>
<li class="nav-item">
<a class="nav-link {% if current_page == 'past' %}active{% endif %}" {% if current_page == 'past' %}aria-current="page"{% endif %} href="/past_events">Vergangene</a>
<a class="nav-link {% if current_page == 'past' %}active{% endif %}" {% if current_page == 'past' %}aria-current="page"{% endif %} href="/past_events/1/">Vergangene</a>
</li>
<!-- <li class="nav-item">-->
<!-- <a class="nav-link {% if current_page == 'preise' %}active{% endif %}" {% if current_page == 'preise' %}aria-current="page"{% endif %} href="/preise">Preise</a>-->

View File

@@ -32,7 +32,7 @@
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-4">
{% for event in events %}
{% for event in page.events %}
<div class="col">
<div class="card h-100 shadow-sm">
<div class="card-body">
@@ -49,13 +49,37 @@
</div>
<p class="text-muted mb-3"><i class="bi bi-calendar"></i> {{ event.event_time.strftime('%A, %d.%m.%Y') }}</p>
<p class="card-text">{{ event.description }}</p>
<a href="event/{{ event.id }}" class="btn btn-sm {% if event.registration_deadline > now %}btn-primary{% else %}btn-secondary{% endif %}">{% if event.registration_deadline > now %}Zur Anmeldung{% else %}Details ansehen{% endif %}</a>
<a href="/event/{{ event.id }}" class="btn btn-sm {% if event.registration_deadline > now %}btn-primary{% else %}btn-secondary{% endif %}">{% if event.registration_deadline > now %}Zur Anmeldung{% else %}Details ansehen{% endif %}</a>
</div>
</div>
</div>
{% endfor %}
</div>
{% if total_pages and total_pages > 1 %}
<nav aria-label="Event pagination">
<ul class="pagination justify-content-center my-4">
<li class="page-item {% if page.page_number <= 1 %}disabled{% endif %}">
<a class="page-link" href="{% if page.page_number == 'home' %}/?page={{ page.page_number - 1 }}{% else %}/past_events/{{ page.page_number - 1 }}/{% endif %}" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
<span class="visually-hidden">Zurück</span>
</a>
</li>
{% for p in range(1, total_pages + 1) %}
<li class="page-item {% if page.page_number == p %}active{% endif %}">
<a class="page-link" href="{% if page.page_number == 'home' %}/?page={{ p }}{% else %}/past_events/{{ p }}/{% endif %}">{{ p }}</a>
</li>
{% endfor %}
<li class="page-item {% if page.page_number >= total_pages %}disabled{% endif %}">
<a class="page-link" href="{% if page.page_number == 'home' %}/?page={{ page.page_number + 1 }}{% else %}/past_events/{{ page.page_number + 1 }}/{% endif %}" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
<span class="visually-hidden">Weiter</span>
</a>
</li>
</ul>
</nav>
{% endif %}
<!-- Modal -->
{{ macros.login_info_modal() }}
{% endblock %}