| import streamlit as st |
| import json |
| import datetime |
| import random |
| import pandas as pd |
| import plotly.express as px |
| import hashlib |
| import time |
| import os |
|
|
| |
| st.set_page_config( |
| page_title="iBank AHR - Banking Redefined", |
| page_icon="π¦", |
| layout="wide", |
| initial_sidebar_state="collapsed" |
| ) |
|
|
| |
| st.markdown(""" |
| <style> |
| .main-header { |
| font-size: 2.5rem; |
| color: #E31837; |
| font-weight: bold; |
| margin-bottom: 1rem; |
| } |
| .account-card { |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| border-radius: 15px; |
| padding: 20px; |
| color: white; |
| margin: 10px 0; |
| } |
| .quick-action { |
| text-align: center; |
| padding: 15px; |
| border-radius: 10px; |
| background-color: #f8f9fa; |
| border: 1px solid #dee2e6; |
| margin: 5px; |
| } |
| .positive { |
| color: #28a745; |
| font-weight: 600; |
| } |
| .negative { |
| color: #dc3545; |
| font-weight: 600; |
| } |
| </style> |
| """, unsafe_allow_html=True) |
|
|
| |
| if 'authenticated' not in st.session_state: |
| st.session_state.authenticated = False |
| if 'current_user' not in st.session_state: |
| st.session_state.current_user = None |
| if 'users' not in st.session_state: |
| st.session_state.users = {} |
| if 'accounts' not in st.session_state: |
| st.session_state.accounts = {} |
| if 'transactions' not in st.session_state: |
| st.session_state.transactions = {} |
| if 'page' not in st.session_state: |
| st.session_state.page = "dashboard" |
|
|
| |
| def init_default_data(): |
| if not st.session_state.users: |
| st.session_state.users = { |
| "demo": { |
| "password": "5f4dcc3b5aa765d61d8327deb882cf99", |
| "name": "Alex Johnson", |
| "email": "alex.johnson@email.com", |
| "phone": "+1 (416) 555-0123", |
| "accounts": ["001-2345678", "002-3456789"] |
| } |
| } |
| |
| if not st.session_state.accounts: |
| st.session_state.accounts = { |
| "001-2345678": { |
| "type": "Chequing", |
| "balance": 12543.67, |
| "currency": "CAD", |
| "nickname": "Everyday Expenses", |
| "transactions": ["TXN001", "TXN002", "TXN003"] |
| }, |
| "002-3456789": { |
| "type": "Savings", |
| "balance": 45678.90, |
| "currency": "CAD", |
| "nickname": "Rainy Day Fund", |
| "transactions": ["TXN004", "TXN005"] |
| } |
| } |
| |
| if not st.session_state.transactions: |
| st.session_state.transactions = { |
| "TXN001": {"id": "TXN001", "date": "2024-01-15", "description": "Grocery Store", "amount": -156.78, "account": "001-2345678"}, |
| "TXN002": {"id": "TXN002", "date": "2024-01-14", "description": "Salary Deposit", "amount": 3500.00, "account": "001-2345678"}, |
| "TXN003": {"id": "TXN003", "date": "2024-01-13", "description": "Online Shopping", "amount": -89.99, "account": "001-2345678"}, |
| "TXN004": {"id": "TXN004", "date": "2024-01-12", "description": "Interest Earned", "amount": 45.67, "account": "002-3456789"}, |
| "TXN005": {"id": "TXN005", "date": "2024-01-10", "description": "Transfer", "amount": 500.00, "account": "002-3456789"}, |
| } |
|
|
| init_default_data() |
|
|
| |
| def hash_password(password): |
| return hashlib.md5(password.encode()).hexdigest() |
|
|
| def login(username, password): |
| if username in st.session_state.users and st.session_state.users[username]["password"] == hash_password(password): |
| st.session_state.authenticated = True |
| st.session_state.current_user = username |
| st.session_state.page = "dashboard" |
| return True |
| return False |
|
|
| def register(username, password, name, email): |
| if username in st.session_state.users: |
| return False, "Username already exists" |
| |
| st.session_state.users[username] = { |
| "password": hash_password(password), |
| "name": name, |
| "email": email, |
| "phone": "", |
| "accounts": [f"001-{random.randint(1000000, 9999999)}"] |
| } |
| |
| account_num = st.session_state.users[username]["accounts"][0] |
| st.session_state.accounts[account_num] = { |
| "type": "Chequing", |
| "balance": 1000.00, |
| "currency": "CAD", |
| "nickname": "Primary Account", |
| "transactions": [] |
| } |
| |
| return True, "Registration successful" |
|
|
| |
| def show_login(): |
| st.markdown('<h1 class="main-header">π¦ iBank AHR</h1>', unsafe_allow_html=True) |
| st.markdown("**Banking Redefined β’ Secure β’ Fast β’ Reliable**") |
| |
| tab1, tab2 = st.tabs(["Login", "Register"]) |
| |
| with tab1: |
| st.subheader("Login to iBank AHR") |
| login_user = st.text_input("Username") |
| login_pass = st.text_input("Password", type="password") |
| |
| if st.button("Login", type="primary", use_container_width=True): |
| if login(login_user, login_pass): |
| st.success("Login successful!") |
| time.sleep(1) |
| st.rerun() |
| else: |
| st.error("Invalid username or password") |
| |
| st.info("**Demo:** Username: `demo` | Password: `password`") |
| |
| with tab2: |
| st.subheader("Create New Account") |
| reg_user = st.text_input("Choose Username") |
| reg_pass = st.text_input("Choose Password", type="password") |
| reg_name = st.text_input("Full Name") |
| reg_email = st.text_input("Email") |
| |
| if st.button("Register", type="secondary", use_container_width=True): |
| success, message = register(reg_user, reg_pass, reg_name, reg_email) |
| if success: |
| st.success(message) |
| time.sleep(1) |
| st.rerun() |
| else: |
| st.error(message) |
| |
| st.markdown("---") |
| st.caption("π 256-bit Encryption β’ π¦ CDIC Insured β’ π¨π¦ Proudly Canadian") |
|
|
| def show_dashboard(): |
| user_data = st.session_state.users[st.session_state.current_user] |
| accounts_data = st.session_state.accounts |
| |
| |
| with st.sidebar: |
| st.markdown(f"### Welcome, {user_data['name'].split()[0]}!") |
| st.caption("Member since 2023") |
| |
| |
| if st.button("π Dashboard", use_container_width=True): |
| st.session_state.page = "dashboard" |
| st.rerun() |
| if st.button("π° Accounts", use_container_width=True): |
| st.session_state.page = "accounts" |
| st.rerun() |
| if st.button("πΈ Transfer", use_container_width=True): |
| st.session_state.page = "transfer" |
| st.rerun() |
| if st.button("π
Pay Bills", use_container_width=True): |
| st.session_state.page = "bills" |
| st.rerun() |
| if st.button("π Investments", use_container_width=True): |
| st.session_state.page = "investments" |
| st.rerun() |
| if st.button("π³ Cards", use_container_width=True): |
| st.session_state.page = "cards" |
| st.rerun() |
| |
| st.markdown("---") |
| |
| if st.button("πͺ Logout", use_container_width=True): |
| st.session_state.authenticated = False |
| st.session_state.current_user = None |
| st.session_state.page = "dashboard" |
| st.rerun() |
| |
| |
| st.markdown("## π Dashboard Overview") |
| |
| |
| total_balance = sum(accounts_data[acc]["balance"] for acc in user_data["accounts"]) |
| col1, col2, col3 = st.columns(3) |
| col1.metric("Total Balance", f"${total_balance:,.2f}", "+2.3%") |
| col2.metric("Monthly Income", "$3,850.00", "$350") |
| col3.metric("Monthly Expenses", "$2,145.67", "-$125") |
| |
| st.markdown("---") |
| |
| |
| st.subheader("Your Accounts") |
| cols = st.columns(len(user_data["accounts"])) |
| for idx, acc_num in enumerate(user_data["accounts"]): |
| acc = accounts_data[acc_num] |
| with cols[idx]: |
| st.markdown(f""" |
| <div class="account-card"> |
| <h3>{acc['nickname']}</h3> |
| <p style="font-size: 1.8rem;"><strong>${acc['balance']:,.2f} {acc['currency']}</strong></p> |
| <p>{acc_num} β’ {acc['type']}</p> |
| </div> |
| """, unsafe_allow_html=True) |
| |
| |
| st.markdown("---") |
| st.subheader("Recent Transactions") |
| |
| for acc_num in user_data["accounts"]: |
| for tx_id in accounts_data[acc_num].get("transactions", []): |
| if tx_id in st.session_state.transactions: |
| tx = st.session_state.transactions[tx_id] |
| amount_class = "positive" if tx["amount"] > 0 else "negative" |
| amount_sign = "+" if tx["amount"] > 0 else "" |
| |
| col1, col2 = st.columns([3, 1]) |
| col1.write(f"**{tx['description']}**") |
| col1.caption(f"{tx['date']} β’ Account: {acc_num}") |
| col2.markdown(f"<span class='{amount_class}'>${amount_sign}{tx['amount']:,.2f}</span>", |
| unsafe_allow_html=True) |
| st.divider() |
|
|
| def show_accounts(): |
| st.title("π° Accounts") |
| user_data = st.session_state.users[st.session_state.current_user] |
| |
| for acc_num in user_data["accounts"]: |
| acc = st.session_state.accounts[acc_num] |
| with st.expander(f"{acc['nickname']} - ${acc['balance']:,.2f} {acc['currency']}", expanded=True): |
| col1, col2 = st.columns(2) |
| col1.metric("Account Number", acc_num) |
| col2.metric("Account Type", acc['type']) |
| col1.metric("Interest Rate", f"{acc.get('interest_rate', 0.5)}%") |
| col2.metric("Available Balance", f"${acc['balance']:,.2f}") |
| |
| if st.button("Back to Dashboard"): |
| st.session_state.page = "dashboard" |
| st.rerun() |
|
|
| def show_transfer(): |
| st.title("πΈ Transfer Funds") |
| user_data = st.session_state.users[st.session_state.current_user] |
| |
| with st.form("transfer_form"): |
| col1, col2 = st.columns(2) |
| |
| with col1: |
| from_acc = st.selectbox( |
| "From Account", |
| user_data["accounts"], |
| format_func=lambda x: f"{st.session_state.accounts[x]['nickname']} (${st.session_state.accounts[x]['balance']:,.2f})" |
| ) |
| amount = st.number_input("Amount ($)", min_value=0.01, value=50.00) |
| |
| with col2: |
| to_acc = st.selectbox( |
| "To Account", |
| [acc for acc in user_data["accounts"] if acc != from_acc] |
| ) |
| memo = st.text_input("Memo", "Transfer") |
| |
| if st.form_submit_button("Transfer Now", type="primary"): |
| if amount <= st.session_state.accounts[from_acc]["balance"]: |
| |
| st.session_state.accounts[from_acc]["balance"] -= amount |
| st.session_state.accounts[to_acc]["balance"] += amount |
| |
| |
| tx_id_out = f"TXN{random.randint(100000, 999999)}" |
| tx_id_in = f"TXN{random.randint(100000, 999999)}" |
| |
| st.session_state.transactions[tx_id_out] = { |
| "id": tx_id_out, |
| "date": datetime.datetime.now().strftime("%Y-%m-%d"), |
| "description": f"Transfer to {st.session_state.accounts[to_acc]['nickname']}", |
| "amount": -amount, |
| "account": from_acc |
| } |
| |
| st.session_state.transactions[tx_id_in] = { |
| "id": tx_id_in, |
| "date": datetime.datetime.now().strftime("%Y-%m-%d"), |
| "description": f"Transfer from {st.session_state.accounts[from_acc]['nickname']}", |
| "amount": amount, |
| "account": to_acc |
| } |
| |
| st.session_state.accounts[from_acc]["transactions"].append(tx_id_out) |
| st.session_state.accounts[to_acc]["transactions"].append(tx_id_in) |
| |
| st.success(f"β
Transfer of ${amount:,.2f} completed!") |
| st.balloons() |
| else: |
| st.error("Insufficient funds!") |
| |
| if st.button("Back to Dashboard"): |
| st.session_state.page = "dashboard" |
| st.rerun() |
|
|
| def show_bills(): |
| st.title("π
Pay Bills") |
| |
| billers = { |
| "Hydro One": 125.67, |
| "Bell Canada": 89.99, |
| "Toronto Water": 45.50, |
| "Property Tax": 320.00, |
| "Credit Card": 450.00 |
| } |
| |
| selected_biller = st.selectbox("Select Biller", list(billers.keys())) |
| |
| col1, col2 = st.columns(2) |
| col1.metric("Biller", selected_biller) |
| col2.metric("Amount Due", f"${billers[selected_biller]:,.2f}") |
| |
| if st.button("Pay Now", type="primary", use_container_width=True): |
| st.success(f"β
Payment of ${billers[selected_biller]:,.2f} to {selected_biller} scheduled!") |
| |
| st.markdown("---") |
| st.subheader("Upcoming Bills") |
| |
| for biller, amount in billers.items(): |
| col1, col2, col3 = st.columns([2, 1, 1]) |
| col1.write(f"**{biller}**") |
| col2.write(f"${amount:,.2f}") |
| col3.button("Pay", key=f"pay_{biller}") |
| |
| if st.button("Back to Dashboard"): |
| st.session_state.page = "dashboard" |
| st.rerun() |
|
|
| def show_investments(): |
| st.title("π Investments") |
| |
| investments = { |
| "RRSP": {"value": 24500.00, "change": "+3.2%"}, |
| "TFSA": {"value": 18750.00, "change": "+1.8%"}, |
| "Stocks": {"value": 32500.00, "change": "-0.5%"}, |
| "Mutual Funds": {"value": 15600.00, "change": "+2.1%"} |
| } |
| |
| total_value = sum(inv["value"] for inv in investments.values()) |
| st.metric("Total Portfolio Value", f"${total_value:,.2f}", "+1.65%") |
| |
| st.markdown("---") |
| |
| for name, data in investments.items(): |
| col1, col2, col3 = st.columns([2, 1, 1]) |
| col1.write(f"**{name}**") |
| col2.write(f"${data['value']:,.2f}") |
| col3.write(data['change']) |
| |
| st.markdown("---") |
| st.subheader("Quick Actions") |
| col1, col2 = st.columns(2) |
| col1.button("Buy", use_container_width=True) |
| col2.button("Sell", use_container_width=True) |
| |
| if st.button("Back to Dashboard"): |
| st.session_state.page = "dashboard" |
| st.rerun() |
|
|
| def show_cards(): |
| st.title("π³ Card Management") |
| |
| cards = [ |
| {"type": "Visa Platinum", "number": "**** 4832", "balance": 1250.00, "status": "Active"}, |
| {"type": "Mastercard Gold", "number": "**** 5917", "balance": 500.00, "status": "Active"}, |
| {"type": "Debit Card", "number": "**** 3268", "balance": "N/A", "status": "Active"} |
| ] |
| |
| for card in cards: |
| with st.expander(f"{card['type']} ({card['number']}) - {card['status']}"): |
| col1, col2, col3 = st.columns(3) |
| col1.metric("Type", card['type']) |
| col2.metric("Status", card['status']) |
| col3.metric("Balance", f"${card['balance']}" if isinstance(card['balance'], (int, float)) else card['balance']) |
| |
| col1, col2 = st.columns(2) |
| col1.button("Lock Card", key=f"lock_{card['number']}") |
| col2.button("Report Lost", key=f"lost_{card['number']}") |
| |
| if st.button("Back to Dashboard"): |
| st.session_state.page = "dashboard" |
| st.rerun() |
|
|
| |
| def main(): |
| if not st.session_state.authenticated: |
| show_login() |
| else: |
| if st.session_state.page == "dashboard": |
| show_dashboard() |
| elif st.session_state.page == "accounts": |
| show_accounts() |
| elif st.session_state.page == "transfer": |
| show_transfer() |
| elif st.session_state.page == "bills": |
| show_bills() |
| elif st.session_state.page == "investments": |
| show_investments() |
| elif st.session_state.page == "cards": |
| show_cards() |
|
|
| if __name__ == "__main__": |
| main() |