"""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"))