Design validé en brainstorming : coquille account_shell (sidebar +
offcanvas), routage /compte/* (une page par section), 3 niveaux d'accès
avec stub d'abonnement, section Compte (email avec re-vérification,
mot de passe, suppression via modale).
Refs #73
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Barre de défilement JS orange (12px) injectée en haut de chaque
.marches_table, collée avec position:sticky, masquée si le tableau
tient dans le viewport
- Scroll contenu dans .dash-spreadsheet-container (overflow-x:hidden)
→ plus de scrollbar navigateur en bas de page
- Drag souris + tactile, clic sur le track, molette/trackpad
- Recalcul automatique au resize et aux re-renders Dash (MutationObserver)
- Test Selenium de non-régression (overflow-x:hidden sur le conteneur)
Sticky headers abandonnés (incompatibles avec scroll contenu).
Portée : 4 pages via la classe partagée .marches_table.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Décrit la refonte de prepare_dashboard_data pour pousser le filtrage au
niveau DuckDB via un nouveau helper dashboard_filters_to_sql, sur le
modèle de filter_query_to_sql / _fetch_page_sql.
Spec validée par brainstorming : inscription avec vérification email,
connexion (Flask-Login), reset password par token stocké en DB,
page compte, SQLite + sqlite3 stdlib, Flask-Mail, CSRF via Flask-WTF.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replace global Polars dataframes in src/utils.py (lines 891-913) with
an on-disk DuckDB database, built at startup from decp_prod.parquet.
Keeps two small search-path frames (df_acheteurs, df_titulaires) in
memory; moves heavy filtering and aggregation to DuckDB via a
query_marches helper that returns pl.DataFrame.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>