Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import pandas as pd | |
| import os | |
| import plotly.express as px | |
| from datetime import datetime | |
| # ------------------------------- | |
| # CONFIG & STYLES | |
| # ------------------------------- | |
| st.set_page_config(page_title="πΈ Expense Tracker", layout="wide") | |
| st.markdown( | |
| """ | |
| <style> | |
| body { | |
| background-color: #f8f9fa; | |
| } | |
| .title { | |
| font-size: 40px; | |
| font-weight: bold; | |
| color: #2c3e50; | |
| text-align: center; | |
| margin-bottom: 10px; | |
| } | |
| .subtitle { | |
| font-size: 18px; | |
| color: #7f8c8d; | |
| text-align: center; | |
| margin-bottom: 30px; | |
| } | |
| .metric-card { | |
| background: black; | |
| padding: 20px; | |
| border-radius: 15px; | |
| text-align: center; | |
| box-shadow: 0px 2px 6px rgba(0,0,0,0.1); | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| # ------------------------------- | |
| # FILE SETUP | |
| # ------------------------------- | |
| CSV_FILE = "expenses.csv" | |
| if not os.path.exists(CSV_FILE): | |
| df = pd.DataFrame(columns=["date", "category", "amount", "description"]) | |
| df.to_csv(CSV_FILE, index=False) | |
| # ------------------------------- | |
| # LOAD DATA | |
| # ------------------------------- | |
| df = pd.read_csv(CSV_FILE) | |
| # ------------------------------- | |
| # SIDEBAR NAVIGATION | |
| # ------------------------------- | |
| st.sidebar.title("π Navigation") | |
| page = st.sidebar.radio("Go to", ["β Add Expense", "π Dashboard", "π Expense Table"]) | |
| st.sidebar.markdown("---") | |
| st.sidebar.write("π‘ Tip: Use filters to explore your expenses easily!") | |
| # ------------------------------- | |
| # PAGE: ADD EXPENSE | |
| # ------------------------------- | |
| if page == "β Add Expense": | |
| st.markdown("<div class='title'>Add New Expense</div>", unsafe_allow_html=True) | |
| with st.form("expense_form", clear_on_submit=True): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| date = st.date_input("Date", datetime.today()) | |
| category = st.selectbox("Category", ["Food", "Transport", "Bills", "Entertainment", "Other"]) | |
| with col2: | |
| amount = st.number_input("Amount", min_value=0.0, step=0.01) | |
| description = st.text_input("Description") | |
| submitted = st.form_submit_button("πΎ Save Expense") | |
| if submitted: | |
| new_expense = pd.DataFrame( | |
| [[date, category, amount, description]], | |
| columns=["date", "category", "amount", "description"], | |
| ) | |
| new_expense.to_csv(CSV_FILE, mode="a", header=False, index=False) | |
| st.success("β Expense saved successfully!") | |
| # ------------------------------- | |
| # PAGE: DASHBOARD | |
| # ------------------------------- | |
| elif page == "π Dashboard": | |
| st.markdown("<div class='title'>Expense Dashboard</div>", unsafe_allow_html=True) | |
| st.markdown("<div class='subtitle'>Visualize your spending habits</div>", unsafe_allow_html=True) | |
| if df.empty: | |
| st.warning("β οΈ No data available yet. Add some expenses first.") | |
| else: | |
| # Metrics Row | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| st.markdown(f"<div class='metric-card'><h3>Total Spent</h3><p>Rs {df['amount'].sum():,.2f}</p></div>", unsafe_allow_html=True) | |
| with col2: | |
| top_cat = df.groupby("category")["amount"].sum().idxmax() | |
| st.markdown(f"<div class='metric-card'><h3>Top Category</h3><p>{top_cat}</p></div>", unsafe_allow_html=True) | |
| with col3: | |
| avg = df["amount"].mean() | |
| st.markdown(f"<div class='metric-card'><h3>Avg. Expense</h3><p>Rs {avg:,.2f}</p></div>", unsafe_allow_html=True) | |
| st.markdown("---") | |
| # Charts | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| fig1 = px.pie(df, names="category", values="amount", title="Expenses by Category", hole=0.4) | |
| st.plotly_chart(fig1, use_container_width=True) | |
| with col2: | |
| df["date"] = pd.to_datetime(df["date"]) | |
| fig2 = px.line(df, x="date", y="amount", title="Expenses Over Time", markers=True) | |
| st.plotly_chart(fig2, use_container_width=True) | |
| # ------------------------------- | |
| # PAGE: EXPENSE TABLE | |
| # ------------------------------- | |
| elif page == "π Expense Table": | |
| st.markdown("<div class='title'>Expense Records</div>", unsafe_allow_html=True) | |
| if df.empty: | |
| st.warning("β οΈ No expenses found. Add some first.") | |
| else: | |
| with st.expander("π Filters", expanded=True): | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| categories = st.multiselect("Filter by Category", df["category"].unique()) | |
| with col2: | |
| date_range = st.date_input("Filter by Date Range", []) | |
| filtered = df.copy() | |
| if categories: | |
| filtered = filtered[filtered["category"].isin(categories)] | |
| if date_range: | |
| if len(date_range) == 2: | |
| start, end = date_range | |
| filtered = filtered[(pd.to_datetime(filtered["date"]) >= pd.to_datetime(start)) & | |
| (pd.to_datetime(filtered["date"]) <= pd.to_datetime(end))] | |
| st.dataframe(filtered, use_container_width=True) | |