lmb-fe/pages/settings_page.py
2026-03-01 00:29:58 +01:00

169 lines
7.1 KiB
Python

import streamlit as st
import requests
import pandas as pd
API_BASE = "https://api.cosmoguard.it/api/v1"
st.title("Impostazioni")
tab_tox, tab_ingredienti, tab_clienti = st.tabs([
"Indicatore Tox Custom",
"Inventario Ingredienti",
"Gestione Clienti",
])
# ---------------------------------------------------------------------------
# TAB 1 — Indicatore Tox Custom
# ---------------------------------------------------------------------------
with tab_tox:
st.subheader("Aggiungi indicatore tossicologico custom")
with st.form("form_tox_indicator"):
cas = st.text_input("CAS Number", placeholder="es. 56-81-5")
col1, col2 = st.columns(2)
with col1:
indicator = st.selectbox("Indicatore", ["NOAEL", "LOAEL", "LD50"])
value = st.number_input("Valore", min_value=0.0, step=0.1)
unit = st.text_input("Unità", placeholder="es. mg/kg bw/day")
with col2:
route = st.text_input("Via di esposizione", placeholder="es. oral, dermal")
toxicity_type = st.selectbox(
"Tipo tossicità",
["", "repeated_dose_toxicity", "acute_toxicity"],
format_func=lambda x: x if x else "— non specificato —"
)
ref = st.text_input("Riferimento / Fonte", placeholder="es. Studio interno 2024")
submitted = st.form_submit_button("Aggiungi indicatore", type="primary")
if submitted:
if not cas or not unit or not route:
st.error("CAS, unità e via di esposizione sono obbligatori.")
else:
payload = {
"cas": cas,
"indicator": indicator,
"value": value,
"unit": unit,
"route": route,
"toxicity_type": toxicity_type or None,
"ref": ref or None,
}
try:
resp = requests.post(f"{API_BASE}/ingredients/add-tox-indicator", json=payload, timeout=30)
if resp.status_code == 200:
data = resp.json()
tox = data.get("data", {}).get("toxicity", {})
best = tox.get("best_case")
st.success(f"Indicatore aggiunto per CAS {cas}.")
if best:
st.info(f"Best case aggiornato: **{best['indicator']}** = {best['value']} {best['unit']} ({best['route']})")
elif resp.status_code == 404:
st.error(f"CAS {cas} non trovato in cache. Esegui prima una ricerca nella pagina Ingredienti.")
else:
st.error(f"Errore {resp.status_code}: {resp.json().get('detail', 'errore sconosciuto')}")
except requests.ConnectionError:
st.error("Impossibile connettersi all'API.")
except Exception as e:
st.error(f"Errore: {e}")
# ---------------------------------------------------------------------------
# TAB 2 — Inventario Ingredienti
# ---------------------------------------------------------------------------
with tab_ingredienti:
st.subheader("Ingredienti nel database")
if st.button("Aggiorna", key="refresh_ingredienti"):
st.rerun()
try:
resp = requests.get(f"{API_BASE}/ingredients/list", timeout=10)
result = resp.json()
if result.get("success") and result.get("data"):
st.caption(f"{result['total']} ingredienti totali")
df = pd.DataFrame(result["data"])
df["dap"] = df["dap"].map({True: "OK", False: "-"})
df["cosing"] = df["cosing"].map({True: "OK", False: "-"})
df["tox"] = df["tox"].map({True: "OK", False: "-"})
df = df.rename(columns={
"cas": "CAS",
"dap": "DAP",
"cosing": "COSING",
"tox": "TOX",
"created_at": "Data Acquisizione",
})
st.dataframe(
df[["CAS", "DAP", "COSING", "TOX", "Data Acquisizione"]],
use_container_width=True,
hide_index=True,
)
else:
st.info("Nessun ingrediente trovato nel database.")
except requests.ConnectionError:
st.error("Impossibile connettersi all'API.")
except Exception as e:
st.error(f"Errore nel caricamento: {e}")
# ---------------------------------------------------------------------------
# TAB 3 — Gestione Clienti
# ---------------------------------------------------------------------------
with tab_clienti:
st.subheader("Clienti registrati")
if st.button("Aggiorna", key="refresh_clienti"):
st.rerun()
try:
resp = requests.get(f"{API_BASE}/ingredients/clients", timeout=10)
result = resp.json()
clienti = result.get("data", []) if result.get("success") else []
except requests.ConnectionError:
st.error("Impossibile connettersi all'API.")
clienti = []
except Exception as e:
st.error(f"Errore nel caricamento: {e}")
clienti = []
if not clienti:
st.info("Nessun cliente trovato.")
else:
for cliente in clienti:
col_nome, col_id, col_btn = st.columns([4, 1, 1])
with col_nome:
st.write(cliente["nome_cliente"])
with col_id:
st.caption(f"id: {cliente['id_cliente']}")
with col_btn:
key = f"del_{cliente['id_cliente']}"
if st.button("Elimina", key=key, type="secondary"):
st.session_state[f"confirm_{cliente['id_cliente']}"] = True
if st.session_state.get(f"confirm_{cliente['id_cliente']}"):
nome = cliente["nome_cliente"]
st.warning(f"Confermi l'eliminazione di **{nome}**?")
col_si, col_no, _ = st.columns([1, 1, 6])
with col_si:
if st.button("Sì, elimina", key=f"yes_{cliente['id_cliente']}", type="primary"):
try:
r = requests.delete(f"{API_BASE}/ingredients/clients/{nome}", timeout=10)
if r.status_code == 200:
st.success(f"Cliente '{nome}' eliminato.")
st.session_state.pop(f"confirm_{cliente['id_cliente']}", None)
st.rerun()
elif r.status_code == 409:
st.error(r.json().get("detail", "Il cliente ha ordini collegati."))
st.session_state.pop(f"confirm_{cliente['id_cliente']}", None)
else:
st.error(f"Errore {r.status_code}: {r.json().get('detail', '')}")
st.session_state.pop(f"confirm_{cliente['id_cliente']}", None)
except requests.ConnectionError:
st.error("Impossibile connettersi all'API.")
with col_no:
if st.button("Annulla", key=f"no_{cliente['id_cliente']}"):
st.session_state.pop(f"confirm_{cliente['id_cliente']}", None)
st.rerun()