To upload files, please first save the app
import streamlit as st
import pandas as pd
import os
import sqlite3
from sqlalchemy import create_engine
# π§ Streamlit configuratie
st.set_page_config(layout="wide")
# π Verbind met SQLite database
engine = create_engine('sqlite:///voeding.db')
# CSS-styling
st.markdown("""
<style>
div[data-testid="stMainBlockContainer"] {
padding-right: 10%;
}
[data-testid="stMainBlockContainer"] {
padding-left: 5%;
padding-right: 5%;
}
[data-testid="stColumn"] {
min-width: 40px !important;
}
/* Aangepaste button styling */
button[kind="secondary"] {
min-width: 40px !important;
max-width: 40px !important;
}
/* Horizontale spacing */
[data-testid="stHorizontalBlock"] {
flex-wrap: nowrap !important;
gap: 10px;
}
body { font-family: 'Segoe UI', sans-serif; }
.stButton>button:hover {background-color: #444;}
</style>
""", unsafe_allow_html=True)
# Maak verbinding met de SQLite-database
def get_connection():
conn = sqlite3.connect("voeding.db")
conn.execute("PRAGMA foreign_keys = ON")
return conn
# Haal alle producten (Id_Nevo en ProductNaam) uit de Voeding-tabel op
def load_producten():
conn = get_connection()
df = pd.read_sql_query("SELECT Id_Nevo, ProductNaam FROM Voeding", conn)
conn.close()
return df
# Haal de maten op voor een gegeven Id_Nevo uit de Maten-tabel
def load_maten(id_nevo):
conn = get_connection()
df = pd.read_sql_query("SELECT Maat, Hoeveelheid, Eenheid FROM Maten WHERE Id_Nevo = ?", conn, params=(int(id_nevo),))
conn.close()
return df
# Bouw een label voor de maatselectie waarin Maat, Hoeveelheid en Eenheid worden gecombineerd
def create_label(row):
if pd.notnull(row["Hoeveelheid"]):
return f"{row['Maat']} ({row['Hoeveelheid']} {row['Eenheid']})"
else:
return f"{row['Maat']} ({row['Eenheid']})"
# Sidebar
st.sidebar.title("Menu")
st.sidebar.header("Navigatie")
option = st.sidebar.radio("Kies een pagina:", ["Klant profiel", "Maaltijdplan", "Over"])
# Pagina-inhoud
if option == "Klant profiel":
st.title("Maaltijdplan")
# π₯ Invoervelden
with st.form("invoer_formulier"):
col1, col2 = st.columns(2)
with col1:
naam = st.text_input("Naam", placeholder="Voornaam Achternaam")
leeftijd = st.number_input("Leeftijd", min_value=0, max_value=120, step=1)
geslacht = st.selectbox("Geslacht", ["Man", "Vrouw"])
with col2:
lengte = st.number_input("Lengte (cm)", min_value=100, max_value=250, step=1)
gewicht = st.number_input("Lichaamsgewicht (kg)", min_value=30.0, max_value=300.0, step=0.1)
vetpercentage = st.number_input("Vetpercentage (%)", min_value=2.0, max_value=60.0, step=0.1)
activiteitsfactor = st.selectbox("Activiteitsniveau", [
"1.2 - Weinig of geen beweging",
"1.375 - Licht actief (1-3x/week)",
"1.55 - Matig actief (3-5x/week)",
"1.725 - Erg actief (6-7x/week)",
"1.9 - Zeer actief (twee keer per dag)"
])
submitted = st.form_submit_button("Bereken")
if submitted:
# π’ Berekeningen
activiteitswaarde = float(activiteitsfactor.split(" - ")[0])
vetvrije_massa = gewicht * (1 - vetpercentage / 100)
bmr = 370 + (21.6 * vetvrije_massa)
onderhoud = bmr * activiteitswaarde
afvallen_berekend = onderhoud - 500
afvallen = max(1500, afvallen_berekend)
# π Resultaten tonen
st.subheader("Resultaat")
col1, col2, col3 = st.columns(3)
col1.metric("BMR", f"{bmr:.0f} kcal/dag")
col2.metric("Onderhoud", f"{onderhoud:.0f} kcal/dag")
afvallen_label = "Afvallen"
if afvallen != afvallen_berekend:
afvallen_label += " (minimum)"
col3.metric(afvallen_label, f"{afvallen:.0f} kcal/dag")
# πΎ Gegevens opslaan in CSV
data = {
"Naam": naam,
"Leeftijd": leeftijd,
"Geslacht": geslacht,
"Lengte_cm": lengte,
"Gewicht_kg": gewicht,
"Vetpercentage": vetpercentage,
"Activiteitsfactor": activiteitswaarde,
"BMR": round(bmr),
"Onderhoud": round(onderhoud),
"Afvallen": round(afvallen)
}
df_nieuw = pd.DataFrame([data])
bestand = "calorie_data.csv"
if os.path.exists(bestand):
df_bestaand = pd.read_csv(bestand)
df_bestaand = pd.concat([df_bestaand, df_nieuw], ignore_index=True)
else:
df_bestaand = df_nieuw
df_bestaand.to_csv(bestand, index=False)
st.success("Resultaat toegevoegd aan CSV-bestand.")
with st.expander("π Bekijk opgeslagen gegevens"):
st.dataframe(df_bestaand, use_container_width=True)
elif option == "Maaltijdplan":
# Hoofdcontent
st.title("DagSchema")
# CSV logica
csv_path = "groepen.csv"
if not os.path.exists(csv_path):
standaard = ["Ontbijt", "Tussendoortje", "Middagmaal", "Tussendoortje", "Avondmaal", "Tussendoortje"]
df = pd.DataFrame({"naam": standaard, "volgorde": list(range(len(standaard)))})
df.to_csv(csv_path, index=False)
df = pd.read_csv(csv_path).sort_values("volgorde").reset_index(drop=True)
def update_csv(new_df):
new_df["volgorde"] = range(len(new_df))
new_df.to_csv(csv_path, index=False)
st.rerun()
# Product inputs
if "product_inputs" not in st.session_state:
st.session_state["product_inputs"] = {}
for index in df.index:
if index not in st.session_state["product_inputs"]:
st.session_state["product_inputs"][index] = [""]
# --- GROEPEN BEHEREN ---
for index, row in df.iterrows():
with st.container(border=True):
cols = st.columns([1, 1, 30, 1, 1])
with cols[0]: # Pijl omhoog
up_disabled = index == 0
if st.button("β", key=f"up_{index}", disabled=up_disabled):
df.iloc[[index - 1, index]] = df.iloc[[index, index - 1]].values
update_csv(df)
with cols[1]: # Pijl omlaag
down_disabled = index == len(df) - 1
if st.button("β", key=f"down_{index}", disabled=down_disabled):
df.iloc[[index, index + 1]] = df.iloc[[index + 1, index]].values
update_csv(df)
with cols[2]: # Naam input
new_name = st.text_input(f"naam_{index}", value=row["naam"], label_visibility="collapsed")
if new_name != row["naam"]:
df.at[index, "naam"] = new_name
update_csv(df)
with cols[3]: # Verwijder groep
if st.button("β", key=f"del_{index}"):
df = df.drop(index).reset_index(drop=True)
st.session_state["product_inputs"].pop(index, None)
update_csv(df)
with cols[4]: # Voeg groep toe
if st.button("β", key=f"add_{index}"):
new_row = pd.DataFrame({"naam": ["Nieuwe groep"], "volgorde": [index + 1]})
df = pd.concat([df.iloc[:index+1], new_row, df.iloc[index+1:]]).reset_index(drop=True)
st.session_state["product_inputs"][index] = [""]
update_csv(df)
st.markdown("""
<hr style="height:1px; margin:0; padding:0; border:none; color:#ccc; background-color:#ccc;"/>
""", unsafe_allow_html=True)
# Product invoer
product_list = st.session_state["product_inputs"].get(index, [])
for prod_index, prod_val in enumerate(product_list):
prod_cols = st.columns([0.5, 9, 1.5, 9])
with prod_cols[0]: # Verwijder product
if st.button("β", key=f"del_prod_{index}_{prod_index}"):
st.session_state["product_inputs"][index].pop(prod_index)
st.rerun()
with prod_cols[1]: # Product input met selectbox
# Haal de lijst met producten op
producten_df = load_producten()
product_options = producten_df["ProductNaam"].tolist()
# Bepaal de initiΓ«le selectie: indien prod_val al in product_options zit, gebruiken we die index
if prod_val in product_options:
init_index = product_options.index(prod_val)
else:
init_index = 0
# Maak de selectbox aan
selected_product = st.selectbox(
f"",
product_options,
index=init_index,
key=f"prod_select_{index}_{prod_index}",
label_visibility="collapsed"
)
# Update de session state met de gekozen waarde
st.session_state["product_inputs"][index][prod_index] = selected_product
with prod_cols[2]:
# Stap 3: Invoerveld voor de gewenste hoeveelheid
hoeveelheid = st.number_input("", min_value=0, value=0, step=1,key=f"hoeveelheid_{index}_{prod_index}", label_visibility="collapsed")
with prod_cols[3]:
# Haal de bijbehorende Id_Nevo op
selected_id_nevo = producten_df.loc[producten_df["ProductNaam"] == selected_product, "Id_Nevo"].iloc[0]
# Stap 2: Haal de maten op voor het gekozen product
maten_df = load_maten(selected_id_nevo)
# Indien er geen maten gevonden worden, gebruiken we de standaardoptie "gram/ml"
if maten_df.empty:
maten_df = pd.DataFrame([{"Maat": "", "Hoeveelheid": None, "Eenheid": "gram/ml"}])
else:
# Voeg de standaardoptie toe als "gram/ml" nog niet voorkomt
if not (maten_df['Maat'] == "gram/ml").any():
default_opt = pd.DataFrame([{"Maat": "", "Hoeveelheid": None, "Eenheid": "gram/ml"}])
maten_df = pd.concat([default_opt, maten_df], ignore_index=True)
# Bouw de lijst met labels voor de maatselectbox
maat_labels = [create_label(row) for _, row in maten_df.iterrows()]
# Plaats de maatselectbox in een placeholder zodat deze telkens opnieuw wordt opgebouwd als het product verandert
measure_placeholder = st.empty()
selected_measure = measure_placeholder.selectbox("", maat_labels, key=f"maat_select_{index}_{prod_index}", label_visibility="collapsed")
# Voeg product toe
add_prod_cols = st.columns([1, 1, 30, 1, 1])
with add_prod_cols[1]:
if st.button("β", key=f"add_prod_{index}"):
st.session_state["product_inputs"][index].append("")
st.rerun()
st.write("") # Visuele scheiding
st.write("")
elif option == "Over":
st.write("Informatie over de app.")
Hi! I can help you with any questions about Streamlit and Python. What would you like to know?