Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import pandas as pd | |
| from datetime import datetime | |
| import os | |
| import matplotlib.pyplot as plt | |
| DATA_FILE = "habits.csv" | |
| # ---------- Page Config ---------- | |
| st.set_page_config(page_title="Habit Tracker", layout="centered") | |
| # ---------- CLEAN LIGHT GRAY UI ---------- | |
| st.markdown(""" | |
| <style> | |
| .block-container { | |
| padding-top: 2rem; | |
| padding-bottom: 2rem; | |
| background-color: #f3f4f6; | |
| } | |
| /* Global text visibility */ | |
| h1, h2, h3, p, div { | |
| color: #0f172a !important; | |
| } | |
| /* Card */ | |
| .card { | |
| background: #ffffff; | |
| padding: 14px; | |
| border-radius: 12px; | |
| border-left: 5px solid #38bdf8; | |
| box-shadow: 0 2px 10px rgba(0,0,0,0.06); | |
| margin-bottom: 10px; | |
| } | |
| /* Streak */ | |
| .streak { | |
| color: #b45309; | |
| font-weight: 600; | |
| } | |
| /* Buttons */ | |
| .stButton > button { | |
| background-color: #38bdf8; | |
| color: white; | |
| border-radius: 8px; | |
| border: none; | |
| } | |
| .stButton > button:hover { | |
| background-color: #0ea5e9; | |
| } | |
| /* Subtle spacing */ | |
| .css-1d391kg { | |
| padding-top: 1rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # ---------- DATA ---------- | |
| def load_data(): | |
| if os.path.exists(DATA_FILE): | |
| return pd.read_csv(DATA_FILE) | |
| return pd.DataFrame(columns=["Habit", "Streak", "Last Completed"]) | |
| def save_data(df): | |
| df.to_csv(DATA_FILE, index=False) | |
| if "habits" not in st.session_state: | |
| st.session_state.habits = load_data() | |
| df = st.session_state.habits | |
| # ---------- TITLE ---------- | |
| st.title("Habit Tracker") | |
| st.write("Build consistency through daily habits") | |
| # ---------- ADD HABIT ---------- | |
| st.subheader("Add Habit") | |
| col1, col2 = st.columns([4, 1]) | |
| with col1: | |
| new_habit = st.text_input("Enter habit", label_visibility="collapsed") | |
| with col2: | |
| if st.button("Add"): | |
| if new_habit.strip(): | |
| if new_habit not in df["Habit"].values: | |
| df = pd.concat( | |
| [df, pd.DataFrame([[new_habit, 0, "Never"]], columns=df.columns)], | |
| ignore_index=True | |
| ) | |
| st.session_state.habits = df | |
| save_data(df) | |
| st.success("Added successfully") | |
| else: | |
| st.warning("Habit already exists") | |
| # ---------- HABITS ---------- | |
| st.subheader("Your Habits") | |
| today = datetime.now().date() | |
| if df.empty: | |
| st.info("No habits added yet") | |
| else: | |
| for i, row in df.iterrows(): | |
| col1, col2, col3 = st.columns([5, 1, 1]) | |
| with col1: | |
| st.markdown(f""" | |
| <div class="card"> | |
| <div style="font-size:16px; font-weight:600;"> | |
| {row['Habit']} | |
| </div> | |
| <div class="streak"> | |
| Streak: {row['Streak']} | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with col2: | |
| if st.button("Done", key=f"done_{i}"): | |
| last_date = row["Last Completed"] | |
| if last_date != "Never": | |
| last_date = pd.to_datetime(last_date).date() | |
| if (today - last_date).days == 1: | |
| df.loc[i, "Streak"] += 1 | |
| elif (today - last_date).days > 1: | |
| df.loc[i, "Streak"] = 1 | |
| else: | |
| df.loc[i, "Streak"] = 1 | |
| df.loc[i, "Last Completed"] = str(today) | |
| st.session_state.habits = df | |
| save_data(df) | |
| st.rerun() | |
| with col3: | |
| if st.button("Delete", key=f"del_{i}"): | |
| df = df[df["Habit"] != row["Habit"]] | |
| st.session_state.habits = df | |
| save_data(df) | |
| st.rerun() | |
| # ---------- GRAPH ---------- | |
| st.subheader("Progress Overview") | |
| if not df.empty: | |
| fig, ax = plt.subplots() | |
| ax.bar(df["Habit"], df["Streak"], color="#38bdf8") | |
| ax.set_facecolor("#f3f4f6") | |
| ax.set_ylabel("Streak") | |
| plt.xticks(rotation=20) | |
| st.pyplot(fig) |