SabaAnver commited on
Commit
c632215
Β·
verified Β·
1 Parent(s): 528c864

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +151 -0
app.py ADDED
@@ -0,0 +1,151 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import os
4
+ import plotly.express as px
5
+ from datetime import datetime
6
+
7
+ # -------------------------------
8
+ # CONFIG & STYLES
9
+ # -------------------------------
10
+ st.set_page_config(page_title="πŸ’Έ Expense Tracker", layout="wide")
11
+
12
+ st.markdown(
13
+ """
14
+ <style>
15
+ body {
16
+ background-color: #f8f9fa;
17
+ }
18
+ .title {
19
+ font-size: 40px;
20
+ font-weight: bold;
21
+ color: #2c3e50;
22
+ text-align: center;
23
+ margin-bottom: 10px;
24
+ }
25
+ .subtitle {
26
+ font-size: 18px;
27
+ color: #7f8c8d;
28
+ text-align: center;
29
+ margin-bottom: 30px;
30
+ }
31
+ .metric-card {
32
+ background: black;
33
+ padding: 20px;
34
+ border-radius: 15px;
35
+ text-align: center;
36
+ box-shadow: 0px 2px 6px rgba(0,0,0,0.1);
37
+ }
38
+ </style>
39
+ """,
40
+ unsafe_allow_html=True,
41
+ )
42
+
43
+ # -------------------------------
44
+ # FILE SETUP
45
+ # -------------------------------
46
+ CSV_FILE = "expenses.csv"
47
+
48
+ if not os.path.exists(CSV_FILE):
49
+ df = pd.DataFrame(columns=["date", "category", "amount", "description"])
50
+ df.to_csv(CSV_FILE, index=False)
51
+
52
+ # -------------------------------
53
+ # LOAD DATA
54
+ # -------------------------------
55
+ df = pd.read_csv(CSV_FILE)
56
+
57
+ # -------------------------------
58
+ # SIDEBAR NAVIGATION
59
+ # -------------------------------
60
+ st.sidebar.title("πŸ“Œ Navigation")
61
+ page = st.sidebar.radio("Go to", ["βž• Add Expense", "πŸ“Š Dashboard", "πŸ“‚ Expense Table"])
62
+
63
+ st.sidebar.markdown("---")
64
+ st.sidebar.write("πŸ’‘ Tip: Use filters to explore your expenses easily!")
65
+
66
+ # -------------------------------
67
+ # PAGE: ADD EXPENSE
68
+ # -------------------------------
69
+ if page == "βž• Add Expense":
70
+ st.markdown("<div class='title'>Add New Expense</div>", unsafe_allow_html=True)
71
+
72
+ with st.form("expense_form", clear_on_submit=True):
73
+ col1, col2 = st.columns(2)
74
+ with col1:
75
+ date = st.date_input("Date", datetime.today())
76
+ category = st.selectbox("Category", ["Food", "Transport", "Bills", "Entertainment", "Other"])
77
+ with col2:
78
+ amount = st.number_input("Amount", min_value=0.0, step=0.01)
79
+ description = st.text_input("Description")
80
+
81
+ submitted = st.form_submit_button("πŸ’Ύ Save Expense")
82
+
83
+ if submitted:
84
+ new_expense = pd.DataFrame(
85
+ [[date, category, amount, description]],
86
+ columns=["date", "category", "amount", "description"],
87
+ )
88
+ new_expense.to_csv(CSV_FILE, mode="a", header=False, index=False)
89
+ st.success("βœ… Expense saved successfully!")
90
+
91
+ # -------------------------------
92
+ # PAGE: DASHBOARD
93
+ # -------------------------------
94
+ elif page == "πŸ“Š Dashboard":
95
+ st.markdown("<div class='title'>Expense Dashboard</div>", unsafe_allow_html=True)
96
+ st.markdown("<div class='subtitle'>Visualize your spending habits</div>", unsafe_allow_html=True)
97
+
98
+ if df.empty:
99
+ st.warning("⚠️ No data available yet. Add some expenses first.")
100
+ else:
101
+ # Metrics Row
102
+ col1, col2, col3 = st.columns(3)
103
+ with col1:
104
+ st.markdown(f"<div class='metric-card'><h3>Total Spent</h3><p>Rs {df['amount'].sum():,.2f}</p></div>", unsafe_allow_html=True)
105
+ with col2:
106
+ top_cat = df.groupby("category")["amount"].sum().idxmax()
107
+ st.markdown(f"<div class='metric-card'><h3>Top Category</h3><p>{top_cat}</p></div>", unsafe_allow_html=True)
108
+ with col3:
109
+ avg = df["amount"].mean()
110
+ st.markdown(f"<div class='metric-card'><h3>Avg. Expense</h3><p>Rs {avg:,.2f}</p></div>", unsafe_allow_html=True)
111
+
112
+ st.markdown("---")
113
+
114
+ # Charts
115
+ col1, col2 = st.columns(2)
116
+ with col1:
117
+ fig1 = px.pie(df, names="category", values="amount", title="Expenses by Category", hole=0.4)
118
+ st.plotly_chart(fig1, use_container_width=True)
119
+
120
+ with col2:
121
+ df["date"] = pd.to_datetime(df["date"])
122
+ fig2 = px.line(df, x="date", y="amount", title="Expenses Over Time", markers=True)
123
+ st.plotly_chart(fig2, use_container_width=True)
124
+
125
+ # -------------------------------
126
+ # PAGE: EXPENSE TABLE
127
+ # -------------------------------
128
+ elif page == "πŸ“‚ Expense Table":
129
+ st.markdown("<div class='title'>Expense Records</div>", unsafe_allow_html=True)
130
+
131
+ if df.empty:
132
+ st.warning("⚠️ No expenses found. Add some first.")
133
+ else:
134
+ with st.expander("πŸ” Filters", expanded=True):
135
+ col1, col2 = st.columns(2)
136
+ with col1:
137
+ categories = st.multiselect("Filter by Category", df["category"].unique())
138
+ with col2:
139
+ date_range = st.date_input("Filter by Date Range", [])
140
+
141
+ filtered = df.copy()
142
+ if categories:
143
+ filtered = filtered[filtered["category"].isin(categories)]
144
+ if date_range:
145
+ if len(date_range) == 2:
146
+ start, end = date_range
147
+ filtered = filtered[(pd.to_datetime(filtered["date"]) >= pd.to_datetime(start)) &
148
+ (pd.to_datetime(filtered["date"]) <= pd.to_datetime(end))]
149
+
150
+ st.dataframe(filtered, use_container_width=True)
151
+