Files
colibre/src/pages/_compte_shell.py
T
Colin Maudry 2bdcfdeb1a Ajoute le drapeau TOUS_ABONNES pour l'accès gratuit
Ouvre les fonctionnalités d'abonné à tout utilisateur connecté tant que
Frisbii n'a pas validé la réception de paiements.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 18:06:27 +02:00

150 lines
4.0 KiB
Python

import dash_bootstrap_components as dbc
from dash import Input, Output, State, callback, dcc, html
from flask_login import current_user
# Définition centralisée des sections de l'espace compte.
# Ajouter une section future = ajouter une ligne ici (+ créer sa page).
SECTIONS = [
{
"key": "abonnement",
"label": "Abonnement",
"href": "/compte/abonnement",
"require_subscription": False,
},
{
"key": "admin",
"label": "Compte",
"href": "/compte/admin",
"require_subscription": False,
},
{
"key": "archives",
"label": "Mes archives",
"href": "/compte/archives",
"require_subscription": True,
},
{
"key": "filtres",
"label": "Mes filtres",
"href": "/compte/filtres",
"require_subscription": True,
},
{
"key": "siret",
"label": "Mon SIRET",
"href": "/compte/siret",
"require_subscription": True,
},
]
def current_user_has_subscription() -> bool:
from src.subscriptions import db
from src.utils import TOUS_ABONNES
if not current_user.is_authenticated:
return False
if TOUS_ABONNES:
return True
return db.has_active_subscription(current_user.id)
def visible_sections(has_subscription: bool) -> list[dict]:
return [s for s in SECTIONS if has_subscription or not s["require_subscription"]]
def guard_redirect(
is_authenticated: bool,
has_subscription: bool,
require_subscription: bool,
path: str,
) -> str | None:
if not is_authenticated:
return f"/connexion?next={path}"
if require_subscription and not has_subscription:
return "/compte/abonnement"
return None
def account_guard(path: str, require_subscription: bool):
href = guard_redirect(
current_user.is_authenticated,
current_user_has_subscription(),
require_subscription,
path,
)
return dcc.Location(href=href, id="compte-guard-redirect") if href else None
def _logout_item():
return dbc.NavItem(
html.Form(
method="POST",
action="/auth/logout",
children=[
dcc.Input(
type="hidden",
id={"type": "csrf-input", "index": "sidebar-logout"},
name="csrf_token",
),
html.Button(
"Déconnexion",
type="submit",
className="nav-link",
style={
"background": "none",
"border": "none",
"width": "100%",
"textAlign": "left",
},
),
],
)
)
def _nav(active: str):
links = [
dbc.NavLink(s["label"], href=s["href"], active=(s["key"] == active))
for s in visible_sections(current_user_has_subscription())
]
return dbc.Nav(links + [_logout_item()], vertical=True, class_name="account-nav")
def account_shell(active: str, contenu):
sidebar = dbc.Col(
html.Div([html.H5("Mon compte", className="mb-3"), _nav(active)]),
md=3,
className="d-none d-md-block",
)
mobile = html.Div(
[
dbc.Button(
"☰ Sections",
id="compte-offcanvas-open",
color="secondary",
outline=True,
className="mb-3",
),
dbc.Offcanvas(
_nav(active),
id="compte-offcanvas",
title="Mon compte",
is_open=False,
),
],
className="d-md-none",
)
content = dbc.Col([mobile, contenu], md=9)
return dbc.Container(dbc.Row([sidebar, content]), className="py-4", fluid=True)
@callback(
Output("compte-offcanvas", "is_open"),
Input("compte-offcanvas-open", "n_clicks"),
State("compte-offcanvas", "is_open"),
prevent_initial_call=True,
)
def _toggle_offcanvas(_n, is_open):
return not is_open