from __future__ import annotations from flask import Flask from config import Config from .cli import register_cli, seed_badges from .extensions import csrf, db, login_manager from .routes import auth, main, scoreboard, settings, tasks from .routes.main import load_icon_svg from .services.badges import sync_existing_badges from .services.bootstrap import ensure_schema_and_admins from .services.dates import MONTH_NAMES, local_now from .services.monthly import archive_months_missing_up_to_previous def create_app(config_class: type[Config] = Config) -> Flask: app = Flask(__name__, static_folder="static", template_folder="templates") app.config.from_object(config_class) app.config["DATA_DIR"].mkdir(parents=True, exist_ok=True) app.config["UPLOAD_FOLDER"].mkdir(parents=True, exist_ok=True) db.init_app(app) login_manager.init_app(app) csrf.init_app(app) with app.app_context(): db.create_all() ensure_schema_and_admins() seed_badges() sync_existing_badges() register_cli(app) app.register_blueprint(main.bp) app.register_blueprint(auth.bp) app.register_blueprint(tasks.bp) app.register_blueprint(scoreboard.bp) app.register_blueprint(settings.bp) app.jinja_env.globals["icon_svg"] = lambda name: load_icon_svg(name, app.static_folder) @app.before_request def ensure_archives(): archive_months_missing_up_to_previous() @app.context_processor def inject_globals(): return { "app_name": app.config["APP_NAME"], "nav_items": [ ("tasks.my_tasks", "Meine Aufgaben", "house"), ("tasks.all_tasks", "Alle", "list"), ("tasks.create", "Neu", "plus"), ("tasks.calendar_view", "Kalender", "calendar"), ("scoreboard.index", "Highscore", "trophy"), ("settings.index", "Optionen", "gear"), ], "icon_svg": lambda name: load_icon_svg(name, app.static_folder), "now_local": local_now(), } @app.template_filter("date_de") def date_de(value): return value.strftime("%d.%m.%Y") if value else "—" @app.template_filter("datetime_de") def datetime_de(value): return value.strftime("%d.%m.%Y, %H:%M") if value else "—" @app.template_filter("month_name") def month_name(value): return MONTH_NAMES[value] return app