lmb-fe/pages/exposition_page.py
2026-02-27 23:29:19 +01:00

146 lines
No EOL
5.9 KiB
Python

import streamlit as st
import requests
import pandas as pd
API_BASE = "https://api.cosmoguard.it/api/v1"
EXPOSURE_ROUTES = ["Dermal", "Oral", "Inhalation", "Ocular"]
st.set_page_config(page_title="Gestione Esposizione", layout="wide")
st.title("Gestione Preset Esposizione")
tab_crea, tab_lista = st.tabs(["Crea Preset", "Preset Esistenti"])
# --- TAB CREAZIONE ---
with tab_crea:
st.subheader("Nuovo Preset di Esposizione")
col1, col2 = st.columns(2)
with col1:
preset_name = st.text_input("Nome Preset", placeholder="es. Crema viso leave-on")
tipo_prodotto = st.text_input("Tipo Prodotto", placeholder="es. Crema")
luogo_applicazione = st.text_input("Luogo Applicazione", placeholder="es. Viso")
with col2:
sup_esposta = st.number_input("Superficie esposta (cm2)", min_value=1, max_value=17500, value=565)
freq_applicazione = st.number_input("Frequenza applicazione (al giorno)", min_value=0.01, value=1.0, step=0.01, format="%.2f")
qta_giornaliera = st.number_input("Quantita giornaliera (g/die)", min_value=0.01, value=1.54, step=0.01, format="%.2f")
st.markdown("---")
col3, col4, col5 = st.columns(3)
with col3:
st.markdown("**Vie esposizione normali**")
esp_normali = st.multiselect("Normali", EXPOSURE_ROUTES, default=["Dermal"], key="esp_norm")
with col4:
st.markdown("**Vie esposizione secondarie**")
esp_secondarie = st.multiselect("Secondarie", EXPOSURE_ROUTES, default=[], key="esp_sec")
with col5:
st.markdown("**Vie esposizione nano**")
esp_nano = st.multiselect("Nano", EXPOSURE_ROUTES, default=["Dermal"], key="esp_nano")
st.markdown("---")
ritenzione = st.number_input("Fattore di ritenzione", min_value=0.01, max_value=1.00, value=1.0, step=0.01, format="%.2f")
# Preview payload
payload = {
"preset_name": preset_name,
"tipo_prodotto": tipo_prodotto,
"luogo_applicazione": luogo_applicazione,
"esp_normali": esp_normali,
"esp_secondarie": esp_secondarie,
"esp_nano": esp_nano,
"sup_esposta": sup_esposta,
"freq_applicazione": freq_applicazione,
"qta_giornaliera": qta_giornaliera,
"ritenzione": ritenzione,
}
with st.expander("Anteprima JSON"):
st.json(payload)
if st.button("Crea Preset", type="primary", disabled=not preset_name):
try:
resp = requests.post(f"{API_BASE}/esposition/create", json=payload, timeout=10)
data = resp.json()
if data.get("success"):
st.success(f"Preset '{preset_name}' creato con successo (id: {data['data']['id_preset']})")
else:
st.error(f"Errore: {data.get('error', 'Sconosciuto')}")
except requests.ConnectionError:
st.error("Impossibile connettersi all'API. Verifica che il server sia attivo.")
except Exception as e:
st.error(f"Errore: {e}")
# --- Session state ---
if "confirm_delete_preset" not in st.session_state:
st.session_state.confirm_delete_preset = None
# --- TAB LISTA ---
with tab_lista:
st.subheader("Preset Esistenti")
if st.button("Aggiorna lista"):
st.session_state.confirm_delete_preset = None
st.rerun()
try:
resp = requests.get(f"{API_BASE}/esposition/presets", timeout=10)
data = resp.json()
if data.get("success") and data.get("data"):
st.info(f"Trovati {data['total']} preset")
df = pd.DataFrame(data["data"])
display_cols = [
"preset_name", "tipo_prodotto", "luogo_applicazione",
"sup_esposta", "freq_applicazione", "qta_giornaliera",
"ritenzione", "esposizione_calcolata", "esposizione_relativa",
]
existing = [c for c in display_cols if c in df.columns]
st.dataframe(df[existing], width="stretch", hide_index=True)
st.divider()
st.subheader("Elimina Preset")
for preset in data["data"]:
name = preset.get("preset_name", "")
col_name, col_btn = st.columns([4, 1])
col_name.write(f"**{name}**")
if st.session_state.confirm_delete_preset == name:
with col_btn:
sub1, sub2 = st.columns(2)
with sub1:
if st.button("Si", key=f"confirm_{name}", type="primary", width="stretch"):
try:
del_resp = requests.delete(f"{API_BASE}/esposition/delete/{name}", timeout=10)
del_data = del_resp.json()
if del_data.get("success"):
st.success(f"Preset '{name}' eliminato")
st.session_state.confirm_delete_preset = None
st.rerun()
else:
st.error(del_data.get("error", "Errore eliminazione"))
except Exception as e:
st.error(f"Errore: {e}")
with sub2:
if st.button("No", key=f"cancel_{name}", width="stretch"):
st.session_state.confirm_delete_preset = None
st.rerun()
else:
with col_btn:
if st.button("Elimina", key=f"del_{name}", width="stretch"):
st.session_state.confirm_delete_preset = name
st.rerun()
else:
st.warning("Nessun preset trovato.")
except requests.ConnectionError:
st.error("Impossibile connettersi all'API. Verifica che il server sia attivo.")
except Exception as e:
st.error(f"Errore nel caricamento: {e}")