add reporting foundation: multipage nav, auth gate, date-range fetch

First increment of the clinical reporting feature (see
docs/requirements-reporting.md and docs/design-reporting.md): moves the
existing live view to pages/1_Live.py, adds a password gate since the
dashboard URL will be shared with the diabetes team, adds
fetch_entries_range/fetch_treatments_range for multi-day report queries,
and adds reporting.py with the core clinical calculations (GMI, %CV,
5-band time-in-range, hypo/hyper event detection per the Battelino et al.
2019 persistence rule). No report pages wired up yet — that's next.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
This commit is contained in:
2026-07-26 20:00:48 +02:00
co-authored by Claude Sonnet 5
parent 7379f6be8c
commit 3ef9a7666a
14 changed files with 1464 additions and 258 deletions
+57
View File
@@ -0,0 +1,57 @@
"""
Gedeelde UI-hulpmiddelen voor app.py en alle pages/*.py.
Elke Streamlit-pagina draait als los script, dus gedeelde constanten/functies
(kleurenpalet, thema-detectie) horen hier thuis in plaats van gedupliceerd te
worden per pagina.
"""
from __future__ import annotations
import streamlit as st
MMOL_HOVERTEMPLATE = "%{x|%d-%m %H:%M} · %{y:.1f} mmol/L<extra></extra>"
# Kleuren per rol, licht/donker — categorale kleuren voor identiteit
# (glucose/insuline/carbs), status-kleuren (vast, nooit hergebruikt) voor
# te laag/te hoog.
PALETTE = {
"light": {
"glucose": "#2a78d6",
"insulin": "#1baf7a",
"carbs": "#eb6834",
"low": "#d03b3b",
"very_low": "#d03b3b",
"high": "#fab219",
"very_high": "#fab219",
"band": "rgba(12,163,12,0.08)",
"grid": "#e1e0d9",
"muted": "#898781",
"text": "#52514e",
"good": "#0ca30c",
},
"dark": {
"glucose": "#3987e5",
"insulin": "#199e70",
"carbs": "#d95926",
"low": "#d03b3b",
"very_low": "#d03b3b",
"high": "#fab219",
"very_high": "#fab219",
"band": "rgba(12,163,12,0.15)",
"grid": "#2c2c2a",
"muted": "#898781",
"text": "#c3c2b7",
"good": "#0ca30c",
},
}
def get_colors() -> dict:
"""Geef de kleurenset terug die past bij het actieve Streamlit-thema."""
theme_type = "light"
try:
theme_type = st.context.theme.type or "light"
except AttributeError:
pass
return PALETTE["dark" if theme_type == "dark" else "light"]