"""TieMeasureFlow Client - Flask Entry Point.""" import json import os from flask import Flask, redirect, url_for, session, request from flask_babel import Babel from flask_wtf.csrf import CSRFProtect from markupsafe import Markup from config import Config def get_locale(): """Get user's preferred language from session or Accept-Language header.""" # 1. User preference in session if "language" in session: return session["language"] # 2. Browser Accept-Language return request.accept_languages.best_match( Config.LANGUAGES.keys(), default="it" ) def create_app() -> Flask: """Application factory.""" app = Flask(__name__) app.config.from_object(Config) # Initialize CSRF protection csrf = CSRFProtect(app) # Initialize Flask-Babel Babel(app, locale_selector=get_locale) # Register blueprints from blueprints.auth import auth_bp from blueprints.measure import measure_bp from blueprints.maker import maker_bp from blueprints.statistics import statistics_bp app.register_blueprint(auth_bp) app.register_blueprint(measure_bp, url_prefix="/measure") app.register_blueprint(maker_bp, url_prefix="/maker") app.register_blueprint(statistics_bp, url_prefix="/statistics") @app.route("/") def index(): """Root redirect to login or dashboard based on session.""" if "user" in session: return redirect(url_for("measure.select_recipe")) return redirect(url_for("auth.login")) @app.route("/set-language/") def set_language(lang): """Set user's preferred language and store in session.""" if lang in Config.LANGUAGES: session["language"] = lang return redirect(request.referrer or url_for("auth.login")) @app.template_filter("tojson_attr") def tojson_attr_filter(value): """JSON encode safe for HTML attributes (x-data, etc.). Unlike |tojson, this escapes double quotes to " so the output can be safely embedded inside double-quoted HTML attributes. The browser decodes the entities before Alpine.js evaluates them. """ rv = json.dumps(value, ensure_ascii=False) rv = ( rv.replace("&", "\\u0026") .replace("<", "\\u003c") .replace(">", "\\u003e") .replace("'", "\\u0027") .replace('"', """) ) return Markup(rv) @app.context_processor def inject_globals(): """Inject global variables into all templates.""" return { "current_user": session.get("user"), "current_theme": session.get("theme", "light"), "current_language": get_locale(), "languages": Config.LANGUAGES, "company_logo": session.get("company_logo"), } return app if __name__ == "__main__": app = create_app() app.run( host=os.getenv("CLIENT_HOST", "0.0.0.0"), port=int(os.getenv("CLIENT_PORT", "5000")), debug=True, )