import streamlit as st import requests import pandas as pd import plotly.express as px from datetime import datetime # ---------- BACKEND & HIDDEN USER ---------- BACKEND_URL = "http://127.0.0.1:8000" # backend requires user_id; keep it hidden (not editable in UI) USER_ID = "user1" # ---------- PAGE CONFIG ---------- st.set_page_config(page_title="FinSync AI", layout="wide", initial_sidebar_state="expanded") # ---------- THEME COLORS ---------- PRIMARY_COLOR = "#6d28d9" # purple ACCENT_COLOR = "#10b981" # green BG_COLOR = "#f5f5f5" # app background CARD_COLOR = "#ffffff" # cards / sidebar TEXT_COLOR = "#111827" # main text # ---------- SIDEBAR (TITLE + NAV) ---------- st.sidebar.markdown( f"""

💰 FinSync AI

Your AI that tracks, budgets & reminds you automatically.

""", unsafe_allow_html=True, ) menu = ["Dashboard", "Expenses", "Budget", "Reminders", "AI Chat"] choice = st.sidebar.radio("Navigation", menu) st.sidebar.markdown( f"
" f"

Hackathon Demo | Powered by Groq LLM

", unsafe_allow_html=True, ) # ---------- CRITICAL CSS FIXES ---------- # This CSS uses stable selectors (html, body, data-testid, header, section[data-testid="stSidebar"]) # to ensure background/text color consistency and avoid the "black top / black sidebar" issues. st.markdown( f""" """, unsafe_allow_html=True, ) # ---------- HELPERS: API CALLS (include user_id param) ---------- def get_expenses(): try: r = requests.get(f"{BACKEND_URL}/expenses", params={"user_id": USER_ID}, timeout=5) if r.ok: return r.json().get("expenses", []) except Exception: pass return [] def add_expense(payload): try: payload["user_id"] = USER_ID r = requests.post(f"{BACKEND_URL}/add_expense", json=payload, timeout=5) return r.ok except Exception: return False def get_budget(): try: r = requests.get(f"{BACKEND_URL}/budget", params={"user_id": USER_ID}, timeout=6) if r.ok: return r.json().get("budget", {}) except Exception: pass return {} def get_reminders(): try: r = requests.get(f"{BACKEND_URL}/reminders", params={"user_id": USER_ID}, timeout=5) if r.ok: return r.json().get("reminders", []) except Exception: pass return [] def add_reminder(payload): try: payload["user_id"] = USER_ID r = requests.post(f"{BACKEND_URL}/reminder", json=payload, timeout=5) return r.ok except Exception: return False def analyze_text(payload): try: payload["user_id"] = USER_ID r = requests.post(f"{BACKEND_URL}/analyze", json=payload, timeout=10) if r.ok: return r.json().get("result", {}) except Exception: pass return {"intent":"error","message":"AI request failed or backend unreachable."} # ---------- UI: DASHBOARD ---------- if choice == "Dashboard": st.header("📊 Dashboard Overview") expenses = get_expenses() if expenses: df = pd.DataFrame(expenses) # normalize types and dates df["amount"] = pd.to_numeric(df["amount"], errors="coerce").fillna(0.0) df["date"] = pd.to_datetime(df["date"], errors="coerce") total = df["amount"].sum() left, right = st.columns([1, 2], gap="large") with left: st.metric("💵 Total Expenses", f"${total:.2f}") # show top categories cat = df.groupby("category")["amount"].sum().sort_values(ascending=False).reset_index() if not cat.empty: st.write("Top categories") st.dataframe(cat.head(5), use_container_width=True) with right: fig = px.pie(cat, names="category", values="amount", title="Spending Breakdown", color_discrete_sequence=px.colors.sequential.Purples) st.plotly_chart(fig, use_container_width=True) st.subheader("Recent Transactions") st.dataframe(df.sort_values("date", ascending=False).head(10), use_container_width=True) else: st.info("No expenses recorded yet. Add one from the Expenses menu.") # ---------- UI: EXPENSES ---------- elif choice == "Expenses": st.header("💸 Add Expense") with st.form("expense_form", clear_on_submit=True): name = st.text_input("Name", placeholder="e.g., Rent, Internet, Groceries") amount = st.number_input("Amount (USD)", min_value=0.0, format="%.2f") category = st.selectbox("Category", ["Rent", "Food", "Utilities", "Subscription", "Shopping", "Misc"]) date = st.date_input("Date", value=datetime.today()) submitted = st.form_submit_button("Add Expense") if submitted: ok = add_expense({ "name": name, "amount": float(amount), "category": category, "date": date.isoformat() }) if ok: st.success("Expense added.") else: st.error("Failed to add expense. Check backend.") st.subheader("All Expenses") expenses = get_expenses() if expenses: df = pd.DataFrame(expenses) df["date"] = pd.to_datetime(df["date"], errors="coerce") st.dataframe(df.sort_values("date", ascending=False), use_container_width=True) else: st.info("No expenses yet.") # ---------- UI: BUDGET ---------- elif choice == "Budget": st.header("📈 AI Budget Recommendation") st.markdown("FinSync AI suggests an allocation based on your expenses.") budget = get_budget() if budget: left, right = st.columns([1, 2], gap="large") with left: st.metric("🛒 Spending", f"{budget.get('Spending',0)*100:.0f}%") st.metric("💰 Savings", f"{budget.get('Savings',0)*100:.0f}%") st.metric("📈 Investments", f"{budget.get('Investments',0)*100:.0f}%") with right: fig = px.pie( names=["Spending", "Savings", "Investments"], values=[budget.get("Spending",0), budget.get("Savings",0), budget.get("Investments",0)], color_discrete_sequence=px.colors.qualitative.Set3 ) st.plotly_chart(fig, use_container_width=True) if budget.get("message"): st.info(budget.get("message")) else: st.info("Budget data not available or backend unreachable.") # ---------- UI: REMINDERS ---------- elif choice == "Reminders": st.header("⏰ Reminders") with st.form("reminder_form", clear_on_submit=True): name = st.text_input("Reminder name", placeholder="e.g., Pay Rent") date = st.date_input("Due date", value=datetime.today()) amount = st.number_input("Amount (optional)", min_value=0.0, format="%.2f") notes = st.text_area("Notes (optional)") submitted = st.form_submit_button("Add Reminder") if submitted: ok = add_reminder({ "name": name, "date": date.isoformat(), "amount": float(amount), "notes": notes }) if ok: st.success("Reminder added.") else: st.error("Failed to add reminder. Check backend.") st.subheader("Your reminders") reminders = get_reminders() if reminders: df = pd.DataFrame(reminders) df["date"] = pd.to_datetime(df["date"], errors="coerce") st.dataframe(df.sort_values("date"), use_container_width=True) else: st.info("No reminders found.") # ---------- UI: AI CHAT ---------- elif choice == "AI Chat": st.header("🤖 AI Chat") st.markdown("Ask FinSync AI to add expenses, show budget, or set reminders. Example: \"Add expense Rent 500\"") prompt = st.text_input("Enter command") if st.button("Send"): if not prompt or prompt.strip() == "": st.warning("Please enter a command.") else: res = analyze_text({"text": prompt}) st.success(res.get("message", "No response")) # ---------- END ----------