CP_EHRENAMT/app/routes/__init__.py
2026-06-25 18:58:44 +02:00

111 lines
3.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""Start-Blueprint.
Hält die Startseite und vorerst schlanke Platzhalter für die übrigen
Navigationsziele (Termine, Team, Profil, Benachrichtigungen). Diese Platzhalter
werden in späteren Sessions durch die echten Ansichten/Blueprints ersetzt
(planung, dienste, dokumente, chat, profil). Interne App: alles login_required.
"""
from flask import Blueprint, current_app, redirect, render_template, request, url_for
from .. import db
from ..auth import current_user, login_required
from ..models import Benachrichtigung
from ..team_scope import team_query
main_bp = Blueprint("main", __name__)
# Theme-Modi (serverseitig, ohne JS): "system" folgt der Systemeinstellung,
# "hell"/"dunkel" überschreiben sie fest. Gespeichert in einem Cookie.
THEME_MODI = ("system", "hell", "dunkel")
@main_bp.app_context_processor
def inject_theme():
"""Aktiven Theme-Modus aus dem Cookie in allen Templates verfügbar machen."""
modus = request.cookies.get("theme", "system")
return {"current_theme": modus if modus in THEME_MODI else "system"}
@main_bp.app_context_processor
def inject_shell_base():
"""Wählt die Layout-Shell je Rolle: Admins bekommen die Sidebar-Shell, alle
anderen die mobile Bottom-Nav-Shell. Templates: {% extends shell_base %}."""
user = current_user()
basis = "base_admin.html" if (user and user.ist_admin) else "base_user.html"
return {"shell_base": basis}
@main_bp.route("/")
@login_required
def index():
return render_template("index.html", user=current_user())
@main_bp.route("/theme", methods=("POST",))
def theme_setzen():
"""Theme-Modus setzen (Cookie) und zur Ausgangsseite zurück. Kein Login nötig,
damit die Einstellung überall greift; CSRF-geschützt wie alle POST-Formulare."""
modus = request.form.get("modus", "system")
if modus not in THEME_MODI:
modus = "system"
# Nur lokale Pfade als Rücksprungziel zulassen (kein Open-Redirect).
ziel = request.form.get("next", "")
if not ziel.startswith("/"):
ziel = url_for("main.index")
antwort = redirect(ziel)
if modus == "system":
antwort.delete_cookie("theme")
else:
antwort.set_cookie(
"theme", modus, max_age=60 * 60 * 24 * 365,
samesite="Lax", httponly=True,
secure=current_app.config.get("SESSION_COOKIE_SECURE", False),
)
return antwort
# --- Platzhalter, damit die Bottom-Nav schon vollständig funktioniert ---------
# „Termine" zeigt auf planung.verfuegbarkeit (Session 6).
@main_bp.route("/team")
@login_required
def team():
return render_template("team.html")
@main_bp.app_context_processor
def inject_benachrichtigungen_zahl():
"""Anzahl ungelesener Benachrichtigungen für die Glocke (0, wenn nicht eingeloggt)."""
user = current_user()
if user is None:
return {"benachrichtigungen_ungelesen": 0}
anzahl = (
team_query(Benachrichtigung)
.filter_by(user_id=user.id, gelesen=False)
.count()
)
return {"benachrichtigungen_ungelesen": anzahl}
@main_bp.route("/benachrichtigungen")
@login_required
def benachrichtigungen():
eintraege = (
team_query(Benachrichtigung)
.filter_by(user_id=current_user().id)
.order_by(Benachrichtigung.erstellt_am.desc())
.all()
)
return render_template("benachrichtigungen.html", eintraege=eintraege)
@main_bp.route("/benachrichtigungen/gelesen", methods=("POST",))
@login_required
def benachrichtigungen_gelesen():
team_query(Benachrichtigung).filter_by(
user_id=current_user().id, gelesen=False
).update({"gelesen": True}, synchronize_session=False)
db.session.commit()
return redirect(url_for("main.benachrichtigungen"))