Spaces:
Runtime error
Runtime error
| import streamlit as st | |
| import pandas as pd | |
| import matplotlib.pyplot as plt | |
| st.set_page_config(page_title="Smart Group Expense Tracker", layout="centered") | |
| st.title("πΈ Smart Group Expense Tracker") | |
| st.caption("Roommates & Trips Edition - Track expenses, split fairly, and settle up easily!") | |
| # --- Session State Init --- | |
| if "participants" not in st.session_state: | |
| st.session_state.participants = [] | |
| if "expenses" not in st.session_state: | |
| st.session_state.expenses = [] | |
| # --- Add Participants --- | |
| with st.expander("β Add Participants"): | |
| new_name = st.text_input("Participant Name", placeholder="e.g. Bilal") | |
| if st.button("Add Participant") and new_name: | |
| if new_name not in st.session_state.participants: | |
| st.session_state.participants.append(new_name) | |
| else: | |
| st.warning("Participant already exists!") | |
| # --- Show Participants --- | |
| if st.session_state.participants: | |
| st.markdown("### π₯ Participants") | |
| st.write(", ".join(st.session_state.participants)) | |
| else: | |
| st.info("Add at least one participant to start tracking.") | |
| # --- Log New Expense --- | |
| st.divider() | |
| st.markdown("### π§Ύ Log New Expense") | |
| if st.session_state.participants: | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| payer = st.selectbox("Paid By", st.session_state.participants) | |
| with col2: | |
| amount = st.number_input("Amount (Rs)", min_value=0.0, step=0.5) | |
| reason = st.text_input("For What?", placeholder="e.g. Dinner, Transport") | |
| if st.button("Add Expense"): | |
| if amount > 0 and payer: | |
| st.session_state.expenses.append({ | |
| "payer": payer, | |
| "amount": amount, | |
| "reason": reason | |
| }) | |
| else: | |
| st.warning("Please enter a valid amount and payer.") | |
| # --- Display Expense Log --- | |
| if st.session_state.expenses: | |
| df = pd.DataFrame(st.session_state.expenses) | |
| st.subheader("π Expense Log") | |
| st.dataframe(df) | |
| # --- Optional Tip Calculation --- | |
| st.subheader("π‘ Add Tip") | |
| tip_percent = st.slider("Tip %", 0, 25, 0) | |
| tip_amount = df["amount"].sum() * (tip_percent / 100) | |
| total = df["amount"].sum() + tip_amount | |
| st.markdown(f"**π° Total Spent (with Tip): Rs. {total:.2f}**") | |
| # --- Final Balances --- | |
| per_person = total / len(st.session_state.participants) | |
| paid = df.groupby("payer")["amount"].sum() | |
| balance = paid - per_person | |
| summary = pd.DataFrame({ | |
| "Paid": paid, | |
| "Balance": balance | |
| }).fillna(0) | |
| st.subheader("π³ Final Balances") | |
| st.dataframe(summary.style.format({"Paid": "Rs. {:.2f}", "Balance": "Rs. {:.2f}"})) | |
| st.caption("πΉ Positive balance = Gets money back | Negative = Owes money") | |
| # --- Pie Chart --- | |
| st.subheader("π Who Paid What?") | |
| fig, ax = plt.subplots() | |
| ax.pie(paid, labels=paid.index, autopct='%1.1f%%', startangle=90) | |
| ax.axis('equal') | |
| st.pyplot(fig) | |
| # --- Download CSV --- | |
| st.subheader("β¬οΈ Download Expense Log") | |
| csv = df.to_csv(index=False).encode("utf-8") | |
| st.download_button( | |
| label="Download CSV", | |
| data=csv, | |
| file_name="group_expenses.csv", | |
| mime="text/csv" | |
| ) | |
| else: | |
| st.info("No expenses logged yet.") | |
| # --- Footer --- | |
| st.markdown("---") | |
| st.markdown( | |
| "<p style='text-align: center; font-size: 14px;'>Made with β€οΈ by <b>Bilal Hussain</b></p>", | |
| unsafe_allow_html=True | |
| ) | |