manaskhan commited on
Commit
b625759
Β·
verified Β·
1 Parent(s): b4cf5bb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +205 -20
app.py CHANGED
@@ -1,20 +1,205 @@
1
- I want to build a Streamlit web app called "πŸ’Έ Expensive Tracker".
2
-
3
- The app should allow users to input and track their expenses. It should look modern, clean, and attractive.
4
-
5
- Requirements:
6
- 1. The app should have a sidebar menu with options like "Add Expense", "View Expenses", and "Summary".
7
- 2. Users can input:
8
- - Date of expense
9
- - Category (Food, Travel, Shopping, Bills, Other)
10
- - Amount
11
- - Notes (optional)
12
- 3. Expenses should be stored in a pandas DataFrame.
13
- 4. Display all expenses in a table with sorting and filtering options.
14
- 5. Add a summary dashboard that shows:
15
- - Total Expenses
16
- - Expenses by Category (pie chart)
17
- - Expenses Over Time (line/bar chart)
18
- 6. Make the design visually appealing using colors, emojis, and modern layout.
19
- 7. Save the code in `app.py`.
20
- 8. Create a `requirements.txt` file listing the dependencies for Hugging Face Spaces deployment.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import plotly.express as px
4
+ from io import StringIO
5
+ from datetime import date
6
+
7
+ # -------------------------------
8
+ # Page config & CSS
9
+ # -------------------------------
10
+ st.set_page_config(page_title="πŸ’Έ Expensive Tracker", page_icon="πŸ’³", layout="centered")
11
+
12
+ st.markdown(
13
+ """
14
+ <style>
15
+ /* Page background gradient */
16
+ .reportview-container {
17
+ background: linear-gradient(135deg,#0f172a,#3b4252);
18
+ color: #e6eef8;
19
+ }
20
+ .stButton>button {
21
+ background: linear-gradient(90deg,#ff7a18,#af002d);
22
+ color: white;
23
+ border-radius: 10px;
24
+ padding: 0.55em 1em;
25
+ font-weight: 600;
26
+ }
27
+ .stButton>button:hover {
28
+ transform: scale(1.02);
29
+ filter: brightness(1.05);
30
+ }
31
+ .card {
32
+ background: rgba(255,255,255,0.06);
33
+ padding: 12px;
34
+ border-radius: 12px;
35
+ border: 1px solid rgba(255,255,255,0.06);
36
+ box-shadow: 0 6px 18px rgba(0,0,0,0.3);
37
+ }
38
+ </style>
39
+ """,
40
+ unsafe_allow_html=True,
41
+ )
42
+
43
+ st.title("πŸ’Έ Expensive Tracker")
44
+ st.caption("Track expenses, analyze spending by category and over time β€” attractive, simple, and portable.")
45
+
46
+ # -------------------------------
47
+ # Initialize in-memory storage
48
+ # -------------------------------
49
+ if "expenses" not in st.session_state:
50
+ # columns: Date, Category, Amount, Notes
51
+ st.session_state.expenses = pd.DataFrame(
52
+ columns=["Date", "Category", "Amount", "Notes"]
53
+ )
54
+
55
+ # -------------------------------
56
+ # Sidebar navigation
57
+ # -------------------------------
58
+ st.sidebar.header("βš™οΈ Menu")
59
+ page = st.sidebar.radio("Choose view", ["Add Expense", "View Expenses", "Summary", "Import / Export"])
60
+
61
+ # Common categories
62
+ CATEGORIES = ["Food", "Travel", "Shopping", "Bills", "Entertainment", "Health", "Other"]
63
+
64
+ # -------------------------------
65
+ # Add Expense
66
+ # -------------------------------
67
+ if page == "Add Expense":
68
+ st.header("Add a new expense")
69
+ with st.form("add_expense_form", clear_on_submit=True):
70
+ c1, c2, c3 = st.columns([1, 1, 1])
71
+ with c1:
72
+ exp_date = st.date_input("Date", value=date.today())
73
+ with c2:
74
+ category = st.selectbox("Category", options=CATEGORIES)
75
+ with c3:
76
+ amount = st.number_input("Amount (₨ or your currency)", min_value=0.0, format="%.2f")
77
+ notes = st.text_area("Notes (optional)", max_chars=200, placeholder="Where/what for?")
78
+ submitted = st.form_submit_button("βž• Add Expense")
79
+
80
+ if submitted:
81
+ new_row = {"Date": pd.to_datetime(exp_date).date(), "Category": category, "Amount": float(amount), "Notes": notes}
82
+ st.session_state.expenses = pd.concat([st.session_state.expenses, pd.DataFrame([new_row])], ignore_index=True)
83
+ st.success("Expense added βœ…")
84
+ st.balloons()
85
+
86
+ if not st.session_state.expenses.empty:
87
+ st.markdown("**Quick preview of latest expenses**")
88
+ st.dataframe(st.session_state.expenses.tail(6).reset_index(drop=True))
89
+
90
+ # -------------------------------
91
+ # View Expenses
92
+ # -------------------------------
93
+ elif page == "View Expenses":
94
+ st.header("All Expenses")
95
+ if st.session_state.expenses.empty:
96
+ st.info("No expenses yet β€” add some from the 'Add Expense' tab.")
97
+ else:
98
+ df = st.session_state.expenses.copy()
99
+ # Allow filtering
100
+ st.markdown("Filter")
101
+ cols = st.columns([1, 1, 1])
102
+ with cols[0]:
103
+ min_date = st.date_input("From", value=df["Date"].min())
104
+ with cols[1]:
105
+ max_date = st.date_input("To", value=df["Date"].max())
106
+ with cols[2]:
107
+ sel_cat = st.multiselect("Category", options=["All"] + CATEGORIES, default=["All"])
108
+ filtered = df[
109
+ (pd.to_datetime(df["Date"]) >= pd.to_datetime(min_date)) &
110
+ (pd.to_datetime(df["Date"]) <= pd.to_datetime(max_date))
111
+ ]
112
+ if sel_cat and "All" not in sel_cat:
113
+ filtered = filtered[filtered["Category"].isin(sel_cat)]
114
+
115
+ st.dataframe(filtered.sort_values(by="Date", ascending=False).reset_index(drop=True))
116
+
117
+ # Option to delete last entry or clear all
118
+ st.markdown("---")
119
+ cdel, cclear = st.columns(2)
120
+ with cdel:
121
+ if st.button("πŸ—‘οΈ Delete last entry"):
122
+ st.session_state.expenses = st.session_state.expenses[:-1].reset_index(drop=True)
123
+ st.success("Last entry removed.")
124
+ with cclear:
125
+ if st.button("⚠️ Clear all expenses"):
126
+ st.session_state.expenses = pd.DataFrame(columns=["Date", "Category", "Amount", "Notes"])
127
+ st.success("All expenses cleared.")
128
+
129
+ # -------------------------------
130
+ # Summary Dashboard
131
+ # -------------------------------
132
+ elif page == "Summary":
133
+ st.header("Summary Dashboard")
134
+ if st.session_state.expenses.empty:
135
+ st.info("No data yet β€” add expenses to see the summary.")
136
+ else:
137
+ df = st.session_state.expenses.copy()
138
+ df["Date"] = pd.to_datetime(df["Date"])
139
+ total = df["Amount"].sum()
140
+ avg = df["Amount"].mean()
141
+ max_exp = df["Amount"].max()
142
+ st.markdown("<div class='card'>", unsafe_allow_html=True)
143
+ c1, c2, c3 = st.columns(3)
144
+ c1.metric("Total Spent", f"{total:,.2f}")
145
+ c2.metric("Average Expense", f"{avg:,.2f}")
146
+ c3.metric("Largest Expense", f"{max_exp:,.2f}")
147
+ st.markdown("</div>", unsafe_allow_html=True)
148
+
149
+ st.markdown("### πŸ“Š Expenses by Category")
150
+ cat_summary = df.groupby("Category", as_index=False)["Amount"].sum().sort_values("Amount", ascending=False)
151
+ fig_pie = px.pie(cat_summary, names="Category", values="Amount", title="Spending by Category", hole=0.4)
152
+ st.plotly_chart(fig_pie, use_container_width=True)
153
+
154
+ st.markdown("### πŸ•’ Expenses Over Time")
155
+ timeseries = df.groupby(pd.Grouper(key="Date", freq="D"))["Amount"].sum().reset_index()
156
+ # Fill missing days for smooth line
157
+ timeseries = timeseries.set_index("Date").resample("D").sum().fillna(0).reset_index()
158
+ fig_line = px.bar(timeseries, x="Date", y="Amount", title="Daily Spending (bar)")
159
+ st.plotly_chart(fig_line, use_container_width=True)
160
+
161
+ st.markdown("### πŸ”Ž Top 5 Expenses")
162
+ st.dataframe(df.nlargest(5, "Amount")[["Date", "Category", "Amount", "Notes"]].reset_index(drop=True))
163
+
164
+ # -------------------------------
165
+ # Import / Export
166
+ # -------------------------------
167
+ elif page == "Import / Export":
168
+ st.header("Import or Export your data")
169
+ st.markdown("You can download your current expenses as a CSV or upload a CSV to load expenses.")
170
+
171
+ # Download
172
+ if st.session_state.expenses.empty:
173
+ st.info("No expenses to export.")
174
+ else:
175
+ csv = st.session_state.expenses.to_csv(index=False)
176
+ st.download_button("⬇️ Download CSV", data=csv, file_name="expenses.csv", mime="text/csv")
177
+
178
+ st.markdown("---")
179
+ st.markdown("Upload a CSV file (columns: Date, Category, Amount, Notes)")
180
+ uploaded = st.file_uploader("Upload CSV", type=["csv"])
181
+ if uploaded is not None:
182
+ try:
183
+ uploaded_df = pd.read_csv(uploaded, parse_dates=["Date"])
184
+ # Basic validation
185
+ required = {"Date", "Category", "Amount"}
186
+ if not required.issubset(set(uploaded_df.columns)):
187
+ st.error("CSV must include at least Date, Category, and Amount columns.")
188
+ else:
189
+ # Append uploaded
190
+ uploaded_df = uploaded_df[["Date", "Category", "Amount", "Notes"]] if "Notes" in uploaded_df.columns else uploaded_df.assign(Notes="")
191
+ uploaded_df["Date"] = pd.to_datetime(uploaded_df["Date"]).dt.date
192
+ st.session_state.expenses = pd.concat([st.session_state.expenses, uploaded_df], ignore_index=True)
193
+ st.success("Uploaded expenses added to your tracker.")
194
+ except Exception as e:
195
+ st.error(f"Failed to parse CSV: {e}")
196
+
197
+ # -------------------------------
198
+ # Footer / Tips
199
+ # -------------------------------
200
+ st.markdown("---")
201
+ st.markdown(
202
+ "<div style='text-align:center;opacity:0.8'>Made with ❀️ β€” Deploy to Hugging Face Spaces (SDK: Streamlit). "
203
+ "Tip: Use the Import/Export tab to keep your data between sessions.</div>",
204
+ unsafe_allow_html=True,
205
+ )