188 lines
6.5 KiB
Python
188 lines
6.5 KiB
Python
import streamlit as st
|
|
import requests
|
|
import pandas as pd
|
|
|
|
<<<<<<< HEAD
|
|
=======
|
|
from functions import cosing_download
|
|
from functions_ui import download_pdf
|
|
|
|
>>>>>>> 584de757bb8f3d254116092e251676a2acfb5c8e
|
|
API_BASE = "https://api.cosmoguard.it/api/v1"
|
|
|
|
st.set_page_config(page_title="Ricerca Ingredienti", layout="wide")
|
|
st.title("Ricerca Ingredienti per CAS")
|
|
|
|
if "ingredient_data" not in st.session_state:
|
|
st.session_state.ingredient_data = None
|
|
if "ingredient_cas" not in st.session_state:
|
|
st.session_state.ingredient_cas = ""
|
|
|
|
cas_input = st.session_state.selected_cas
|
|
force_refresh = st.session_state.force_refresh if "force_refresh" in st.session_state else False
|
|
|
|
if cas_input:
|
|
with st.spinner(f"Ricerca in corso per {cas_input}..."):
|
|
try:
|
|
resp = requests.post(
|
|
f"{API_BASE}/ingredients/search",
|
|
json={"cas": cas_input, "force": force_refresh},
|
|
timeout=120,
|
|
)
|
|
result = resp.json()
|
|
|
|
if result.get("success") and result.get("data"):
|
|
st.session_state.ingredient_data = result["data"]
|
|
st.session_state.ingredient_cas = cas_input
|
|
st.success(f"Ingrediente {cas_input} trovato")
|
|
else:
|
|
st.session_state.ingredient_data = None
|
|
st.error(result.get("error", f"Nessun dato per CAS {cas_input}"))
|
|
|
|
except requests.ConnectionError:
|
|
st.error("Impossibile connettersi all'API. Verifica che il server sia attivo.")
|
|
except Exception as e:
|
|
st.error(f"Errore: {e}")
|
|
|
|
|
|
data = st.session_state.ingredient_data
|
|
|
|
if data is None:
|
|
st.info("Effettua una ricerca per visualizzare i risultati.")
|
|
else:
|
|
cas = data.get("cas", "")
|
|
st.subheader(f"Ingrediente: {cas}")
|
|
|
|
# --- Header con INCI e data ---
|
|
col_h1, col_h2 = st.columns(2)
|
|
with col_h1:
|
|
inci = data.get("inci") or []
|
|
st.markdown(f"**INCI:** {', '.join(inci) if inci else 'N/A'}")
|
|
with col_h2:
|
|
st.markdown(f"**Data creazione:** {data.get('creation_date', 'N/A')}")
|
|
|
|
st.markdown("---")
|
|
|
|
# --- DAP Info ---
|
|
st.subheader("DAP Info")
|
|
dap = data.get("dap_info")
|
|
if dap:
|
|
col_d1, col_d2, col_d3 = st.columns(3)
|
|
with col_d1:
|
|
st.metric("Peso Molecolare (Da)", dap.get("molecular_weight", "N/A"))
|
|
st.metric("Log Pow", dap.get("log_pow", "N/A"))
|
|
with col_d2:
|
|
st.metric("TPSA", dap.get("tpsa", "N/A"))
|
|
st.metric("Punto Fusione (C)", dap.get("melting_point") or "N/A")
|
|
with col_d3:
|
|
dap_val = dap.get("dap_value", 0.5)
|
|
st.metric("DAP Value", f"{dap_val * 100:.0f}%")
|
|
st.metric("Alta Ionizzazione", dap.get("high_ionization") or "N/A")
|
|
else:
|
|
st.warning("Dati DAP non disponibili")
|
|
|
|
st.markdown("---")
|
|
|
|
# --- COSING Info ---
|
|
st.subheader("COSING Info")
|
|
cosing_list = data.get("cosing_info")
|
|
if cosing_list:
|
|
for i, cosing in enumerate(cosing_list):
|
|
if len(cosing_list) > 1:
|
|
st.markdown(f"**Voce {i + 1}**")
|
|
|
|
col_c1, col_c2 = st.columns(2)
|
|
with col_c1:
|
|
names = cosing.get("common_names", [])
|
|
st.markdown(f"**Nomi comuni:** {', '.join(names) if names else 'N/A'}")
|
|
st.markdown(f"**INCI:** {', '.join(cosing.get('inci', [])) or 'N/A'}")
|
|
st.markdown(f"**CAS:** {', '.join(cosing.get('cas', [])) or 'N/A'}")
|
|
|
|
funcs = cosing.get("functionName", [])
|
|
if funcs:
|
|
st.markdown("**Funzioni:**")
|
|
for f in funcs:
|
|
st.markdown(f"- {f}")
|
|
|
|
ref_no = cosing.get("reference", "")
|
|
if ref_no:
|
|
pdf_bytes = cosing_download(ref_no)
|
|
|
|
if isinstance(pdf_bytes, bytes):
|
|
st.download_button(
|
|
label="Download CosIng PDF",
|
|
data=pdf_bytes,
|
|
file_name=f"{cas_input}_cosing.pdf",
|
|
mime="application/pdf"
|
|
)
|
|
else:
|
|
st.error(pdf_bytes)
|
|
|
|
|
|
with col_c2:
|
|
annex = cosing.get("annex", [])
|
|
if annex:
|
|
st.markdown("**Annex/Restrizioni:**")
|
|
for a in annex:
|
|
st.markdown(f"- {a}")
|
|
else:
|
|
st.markdown("**Annex:** Nessuna restrizione")
|
|
|
|
other = cosing.get("otherRestrictions", [])
|
|
if other:
|
|
st.markdown("**Altre restrizioni:**")
|
|
for o in other:
|
|
st.markdown(f"- {o}")
|
|
|
|
restriction = cosing.get("cosmeticRestriction", "")
|
|
if restriction:
|
|
st.warning(f"Restrizione cosmetica: {restriction}")
|
|
|
|
link_opinions = cosing.get("sccsOpinionUrls", [])
|
|
if link_opinions:
|
|
st.markdown("**SCCS Opinions:**")
|
|
for url in link_opinions:
|
|
st.link_button("View SCCS Opinion", url)
|
|
|
|
if i < len(cosing_list) - 1:
|
|
st.divider()
|
|
else:
|
|
st.warning("Dati COSING non disponibili")
|
|
|
|
st.markdown("---")
|
|
|
|
# --- Toxicity ---
|
|
st.subheader("Tossicologia")
|
|
tox = data.get("toxicity")
|
|
if tox:
|
|
# Best case highlight
|
|
best = tox.get("best_case")
|
|
if best:
|
|
st.success(
|
|
f"Miglior indicatore: **{best['indicator']}** = {best['value']} {best['unit']} "
|
|
f"({best['route']}) — Fattore: {tox.get('factor', 'N/A')}"
|
|
)
|
|
|
|
download_pdf(
|
|
casNo=cas_input,
|
|
origin=best.get("source"),
|
|
link=best.get("ref")
|
|
)
|
|
|
|
# Indicators table
|
|
indicators = tox.get("indicators", [])
|
|
if indicators:
|
|
df = pd.DataFrame(indicators)
|
|
col_order = ["indicator", "value", "unit", "route", "toxicity_type"]
|
|
existing = [c for c in col_order if c in df.columns]
|
|
df = df[existing]
|
|
df.columns = ["Indicatore", "Valore", "Unita", "Via", "Tipo"][:len(existing)]
|
|
st.dataframe(df, width="stretch", hide_index=True)
|
|
else:
|
|
st.warning("Dati tossicologici non disponibili")
|
|
|
|
st.markdown("---")
|
|
|
|
# --- JSON completo ---
|
|
with st.expander("JSON completo"):
|
|
st.json(data)
|