Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import pandas as pd | |
| import joblib | |
| import numpy as np | |
| import warnings | |
| from streamlit.components.v1 import html | |
| import time # For simulating loading | |
| # --- Set page configuration --- | |
| st.set_page_config( | |
| page_title="CreditIQ - AI-Powered Credit Expenditure Prediction", | |
| page_icon="💳", | |
| layout="wide", # Use wide layout to better accommodate complex design | |
| initial_sidebar_state="collapsed" # Hide sidebar to give full canvas | |
| ) | |
| # --- Initialize session state for page management --- | |
| if 'active_page' not in st.session_state: | |
| st.session_state.active_page = 'home' | |
| if 'show_prediction' not in st.session_state: | |
| st.session_state.show_prediction = False | |
| if 'predicted_value' not in st.session_state: | |
| st.session_state.predicted_value = 0.0 | |
| warnings.filterwarnings('ignore') | |
| st.markdown(""" | |
| <style> | |
| /* Hide Streamlit's default header, footer, and hamburger menu */ | |
| #MainMenu, header, footer { visibility: hidden; } | |
| /* Remove padding from the main block container for a full-width feel */ | |
| .block-container { | |
| padding: 0 !important; | |
| } | |
| [class*="st-key-dismiss_modal_btn"] { | |
| display:none; | |
| } | |
| div.stButton > button { | |
| background: transparent; | |
| color: var(--gray-light); | |
| text-decoration: none !important; | |
| font-weight: 500; | |
| transition: all 0.3s ease; | |
| font-family: "Times New Roman " !important; /* Font */ | |
| font-size: 18px !important; /* Font size */ | |
| border: none; /* Remove border */ | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| width:110px; | |
| height:50px; | |
| margin-top:-5px; | |
| position:fixed; | |
| z-index:10000000; | |
| } | |
| div[data-testid="stSelectbox"] | |
| {{ | |
| background-color: white !important; | |
| position: relative; | |
| border-bottom:1px solid #ccc; | |
| border-radius:0px; | |
| }} | |
| div[data-testid="stTextInput"]{{ | |
| }} | |
| div[data-testid="stTextInput"] > div >div {{ | |
| background-color: rgba(255, 158, 87, 0.12) !important; | |
| }} | |
| div[data-testid="stTextInputRootElement"]{{ | |
| border: 1px solid white !important; | |
| }} | |
| /* Hover effect */ | |
| div.stButton > button:hover { | |
| color: var(--white) !important; | |
| transform: none !important; | |
| } | |
| div.stButton > button.active { | |
| color: var(--white) !important; | |
| } | |
| /* Style the sidebar to have a modern, dark look */ | |
| section[data-testid="stSidebar"] {{ | |
| backdrop-filter: blur(10px); | |
| background: rgba(255, 255, 255, 0.15); | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.01); | |
| height:100px; | |
| [data-testid="stSidebar"] h2 {{ | |
| color: #FFFFFF; /* White headers in the sidebar */ | |
| font-family:time new roman !important; | |
| }} | |
| [data-testid="stSidebar"] .st-emotion-cache-1629p8f a {{ | |
| color: #94A3B8; /* Lighter text color for links */ | |
| font-family:time new roman !important; | |
| }} | |
| [data-testid="stImageContainer"]>img{{ | |
| max-width:70% !important; | |
| margin-top:-70px; | |
| }} | |
| div[data-testid="stMarkdownContainer"] >p{{ | |
| font-family:time new roman !important; | |
| }} | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # --- Inject Custom HTML, CSS, and Inline JavaScript --- | |
| # This block defines the sophisticated styling and background animations, | |
| # navigation, and overall page structure. | |
| # Streamlit components will be injected into specific HTML placeholders. | |
| st.markdown(f""" | |
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <title>CreditIQ - AI-Powered Credit Expenditure Prediction</title> | |
| <meta name="description" content="Professional AI-powered credit card expenditure prediction platform. Get accurate spending forecasts with advanced machine learning algorithms."> | |
| <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><text y='.9em' font-size='90'>💳</text></svg>"> | |
| <link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap" rel="stylesheet"> | |
| <link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css" rel="stylesheet"> | |
| <style> | |
| /* General Resets */ | |
| * {{ | |
| margin: 0; | |
| padding: 0; | |
| box-sizing: border-box; | |
| font-family:time new roman !important; | |
| }} | |
| html, body, .main {{ | |
| margin: 0; | |
| padding: 0; | |
| height: 100%; | |
| overflow-x: hidden; | |
| position: relative; | |
| }} | |
| i[class^="fa"], i[class*=" fa"] {{ | |
| font-family: "Font Awesome 6 Free" !important; | |
| font-weight: 900 !important; | |
| font-style: normal !important; | |
| display: inline-block !important; | |
| text-rendering: auto; | |
| -webkit-font-smoothing: antialiased; | |
| }} | |
| /* Custom Button Styling for Navigation */ | |
| .nav-button {{ | |
| background: transparent !important; | |
| color: var(--gray-light) !important; | |
| border: none !important; | |
| font-weight: 500 !important; | |
| font-family: 'Inter', sans-serif !important; | |
| padding: 0 !important; | |
| text-align: center; | |
| position: relative; | |
| transition: all 0.3s ease; | |
| box-shadow: none !important; | |
| }} | |
| [class*="st-key-nav_"]:hover {{ | |
| color: var(--white) !important; | |
| transform: none !important; | |
| }} | |
| [class*="st-key-nav_home_home"]::after | |
| {{ | |
| content: ''; | |
| position: absolute; | |
| bottom: -8px; | |
| left: 0; | |
| width: 100%; | |
| height: 2px; | |
| background: var(--gradient-accent); | |
| color: var(--white) !important; | |
| margin-left:15px; | |
| }} | |
| [class*="st-key-nav_about_about"]::after | |
| {{ | |
| content: ''; | |
| position: absolute; | |
| bottom: -8px; | |
| left: 0; | |
| width: 100%; | |
| height: 2px; | |
| background: var(--gradient-accent); | |
| color: var(--white) !important; | |
| margin-left:15px; | |
| }} | |
| [class*="st-key-nav_predictor_predictor"]::after | |
| {{ | |
| content: ''; | |
| position: absolute; | |
| bottom: -8px; | |
| left: 0; | |
| width: 100%; | |
| height: 2px; | |
| background: var(--gradient-accent); | |
| color: var(--white) !important; | |
| margin-left:15px; | |
| }} | |
| [class*="st-key-nav_features_features"]::after | |
| {{ | |
| content: ''; | |
| position: absolute; | |
| bottom: -8px; | |
| left: 0; | |
| width: 100%; | |
| height: 2px; | |
| background: var(--gradient-accent); | |
| color: var(--white) !important; | |
| margin-left:15px; | |
| }} | |
| [class*="st-key-nav_contact_contact"]::after | |
| {{ | |
| content: ''; | |
| position: absolute; | |
| bottom: -8px; | |
| left: 0; | |
| width: 45%; | |
| height: 2px; | |
| background: var(--gradient-accent); | |
| color: var(--white) !important; | |
| margin-left:15px; | |
| }} | |
| /* Root Variables for Colors and Shadows */ | |
| :root {{ | |
| --primary: #4F46E5; | |
| --primary-dark: #3730A3; | |
| --secondary: #06B6D4; | |
| --accent: #8B5CF6; | |
| --success: #10B981; | |
| --warning: #F59E0B; | |
| --error: #EF4444; | |
| --dark: #0F172A; | |
| --dark-light: #1E293B; | |
| --gray: #64748B; | |
| --gray-light: #94A3B8; | |
| --white: #FFFFFF; | |
| --glass-bg: rgba(255, 255, 255, 0.1); | |
| --glass-nav: rgba(255, 255, 255, 0.03); | |
| --glass-border: rgba(255, 255, 255, 0.2); | |
| --gradient-primary: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| --gradient-secondary: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); | |
| --gradient-accent: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); | |
| --shadow-sm: 0 2px 8px rgba(0, 0, 0, 0.1); | |
| --shadow-md: 0 8px 32px rgba(0, 0, 0, 0.15); | |
| --shadow-lg: 0 16px 64px rgba(0, 0, 0, 0.2); | |
| }} | |
| /* Body and App Background */ | |
| body, .stApp {{ | |
| font-family: 'Inter', sans-serif; | |
| background: linear-gradient(135deg, #0F172A 0%, #1E293B 100%); | |
| color: var(--white); | |
| line-height: 1.6; | |
| overflow-x: hidden; | |
| height: 100vh; | |
| position: relative; /* Needed for absolute positioning of bg-animation */ | |
| }} | |
| /* Streamlit's main content wrapper */ | |
| .st-emotion-block-container {{ | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 0 2rem; | |
| position: relative; | |
| z-index: 1; /* Ensure content is above backgrounds */ | |
| }} | |
| /* Background Animation */ | |
| .bg-animation {{ | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: -2; /* Ensure it's behind everything */ | |
| background: linear-gradient(45deg, #667eea, #764ba2, #f093fb, #f5576c, #4facfe, #00f2fe); | |
| background-size: 400% 400%; | |
| animation: gradientShift 15s ease infinite; | |
| }} | |
| @keyframes gradientShift {{ | |
| 0% {{ background-position: 0% 50%; }} | |
| 50% {{ background-position: 100% 50%; }} | |
| 100% {{ background-position: 0% 50%; }} | |
| }} | |
| /* Floating Shapes Animation */ | |
| .floating-shapes {{ | |
| position: fixed; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| z-index: -1; /* Above bg-animation, below content */ | |
| pointer-events: none; /* Allows clicks to pass through */ | |
| }} | |
| .shape {{ | |
| position: absolute; | |
| opacity: 0.1; | |
| animation: float 20s infinite ease-in-out; | |
| }} | |
| .shape:nth-child(1) {{ | |
| top: 10%; | |
| left: 10%; | |
| width: 80px; | |
| height: 80px; | |
| background: var(--gradient-accent); | |
| border-radius: 50%; | |
| animation-delay: 0s; | |
| }} | |
| .shape:nth-child(2) {{ | |
| top: 70%; | |
| right: 10%; | |
| width: 120px; | |
| height: 120px; | |
| background: var(--gradient-secondary); | |
| border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; | |
| animation-delay: 5s; | |
| }} | |
| .shape:nth-child(3) {{ | |
| bottom: 20%; | |
| left: 20%; | |
| width: 100px; | |
| height: 100px; | |
| background: var(--gradient-primary); | |
| border-radius: 20px; | |
| transform: rotate(45deg); | |
| animation-delay: 10s; | |
| }} | |
| @keyframes float {{ | |
| 0%, 100% {{ transform: translateY(0px) rotate(0deg); }} | |
| 33% {{ transform: translateY(-30px) rotate(120deg); }} | |
| 66% {{ transform: translateY(15px) rotate(240deg); }} | |
| }} | |
| /* Navigation */ | |
| .navbar {{ | |
| position: fixed; | |
| top: 0; | |
| width: 100%; | |
| z-index: 1000; | |
| transition: all 0.3s ease; | |
| background: var(--glass-nav); | |
| backdrop-filter: blur(20px); | |
| box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2); | |
| }} | |
| .navbar.scrolled {{ | |
| background: rgba(15, 23, 42, 0.98); | |
| box-shadow: var(--shadow-md); | |
| }} | |
| .nav-container {{ | |
| max-width: 1500px; | |
| margin: 0 auto; | |
| padding: 0 2rem; | |
| display: flex; | |
| justify-content: space-between; | |
| align-items: center; | |
| height: 80px; | |
| }} | |
| .logo {{ | |
| font-size: 1.8rem; | |
| font-weight: 800; | |
| background: var(--gradient-accent); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| text-decoration: none; | |
| }} | |
| .nav-menu {{ | |
| display: flex; | |
| list-style: none; | |
| gap: 2rem; | |
| align-items: center; | |
| }} | |
| .nav-link {{ | |
| color: var(--gray-light); | |
| text-decoration: none !important; | |
| font-weight: 500; | |
| transition: all 0.3s ease; | |
| position: relative; | |
| }} | |
| .nav-link:hover, | |
| .nav-link.active {{ | |
| color: var(--white); | |
| }} | |
| .nav-link::after {{ | |
| content: ''; | |
| position: absolute; | |
| bottom: -5px; | |
| left: 0; | |
| width: 0; | |
| height: 2px; | |
| background: var(--gradient-accent); | |
| transition: width 0.3s ease; | |
| }} | |
| .nav-link:hover::after, | |
| .nav-link.active::after {{ | |
| width: 100%; | |
| }} | |
| .cta-btn {{ | |
| background: var(--gradient-accent); | |
| color: var(--white); | |
| padding: 0.75rem 1.5rem; | |
| border-radius: 50px; | |
| text-decoration: none; | |
| font-weight: 600; | |
| transition: all 0.3s ease; | |
| box-shadow: var(--shadow-sm); | |
| }} | |
| .cta-btn:hover {{ | |
| transform: translateY(-2px); | |
| box-shadow: var(--shadow-md); | |
| }} | |
| .mobile-menu-btn {{ | |
| display: none; | |
| background: none; | |
| border: none; | |
| color: var(--white); | |
| font-size: 1.5rem; | |
| cursor: pointer; | |
| }} | |
| /* Hero Section */ | |
| .hero {{ | |
| height: 900px; | |
| display: flex; | |
| align-items: center; | |
| position: relative; | |
| overflow: hidden; | |
| padding-top: 80px; /* Account for fixed navbar */ | |
| margin-top:-250px; | |
| }} | |
| .hero-bg {{ | |
| position: absolute; | |
| top: 0; | |
| left: 0; | |
| width: 100%; | |
| height: 100%; | |
| background: var(--gradient-primary); | |
| opacity: 0.1; | |
| /*animation: gradientShift 15s ease infinite;*/ | |
| z-index: -1; | |
| }} | |
| .hero-container {{ | |
| max-width: 1200px; | |
| margin: 0 auto; | |
| padding: 0 2rem; | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 4rem; | |
| align-items: center; | |
| position: relative; | |
| z-index: 1; | |
| width: 100%; /* Ensure it takes full width of st.container */ | |
| }} | |
| .hero-content h1 {{ | |
| font-size: 4rem; | |
| font-weight: 900; | |
| line-height: 1.1; | |
| margin-bottom: 1.5rem; | |
| background: linear-gradient(135deg, #fff, #e2e8f0); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| }} | |
| .hero-content .highlight {{ | |
| background: var(--gradient-accent); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| }} | |
| .hero-content p {{ | |
| font-size: 1.2rem; | |
| color: var(--gray-light); | |
| margin-bottom: 2rem; | |
| max-width: 500px; | |
| }} | |
| .hero-buttons {{ | |
| display: flex; | |
| gap: 1rem; | |
| flex-wrap: wrap; | |
| }} | |
| .btn-primary {{ | |
| background: var(--gradient-accent); | |
| color: var(--white); | |
| padding: 1rem 2rem; | |
| border-radius: 50px; | |
| text-decoration: none; | |
| font-weight: 600; | |
| transition: all 0.3s ease; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| box-shadow: var(--shadow-md); | |
| }} | |
| .btn-primary:hover {{ | |
| transform: translateY(-3px); | |
| box-shadow: var(--shadow-lg); | |
| }} | |
| .btn-secondary {{ | |
| background: transparent; | |
| color: var(--white); | |
| padding: 1rem 2rem; | |
| border: 2px solid var(--glass-border); | |
| border-radius: 50px; | |
| text-decoration: none; | |
| font-weight: 600; | |
| transition: all 0.3s ease; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| }} | |
| .btn-secondary:hover {{ | |
| background: var(--glass-bg); | |
| border-color: var(--white); | |
| }} | |
| .hero-visual {{ | |
| position: relative; | |
| height: 500px; /* Fixed height for visual consistency */ | |
| width: 100%; | |
| }} | |
| .hero-card {{ | |
| position: absolute; | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(20px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 24px; | |
| padding: 2rem; | |
| box-shadow: var(--shadow-lg); | |
| animation: float 6s ease-in-out infinite; | |
| }} | |
| .hero-card:nth-child(1) {{ | |
| top: 0; | |
| left: 0; | |
| width: 280px; | |
| animation-delay: 0s; | |
| }} | |
| .hero-card:nth-child(2) {{ | |
| top: 100px; | |
| right: 0; | |
| width: 250px; | |
| animation-delay: 2s; | |
| }} | |
| .hero-card:nth-child(3) {{ | |
| bottom: 0; | |
| left: 50px; | |
| width: 200px; | |
| animation-delay: 4s; | |
| }} | |
| /* Main Content Pages */ | |
| /* Streamlit will show/hide these based on st.session_state */ | |
| .page {{ | |
| display: none; /* Controlled by Streamlit's Python logic */ | |
| height: 900px; | |
| padding: 120px 0 80px; /* Padding for header/footer */ | |
| margin-top: -250px; | |
| }} | |
| .page.active {{ | |
| display: block; /* Shown by Streamlit */ | |
| margin-top: -100px !important; | |
| }} | |
| .page-header {{ | |
| text-align: center; | |
| margin-bottom: 4rem; | |
| margin-top:-50px; | |
| }} | |
| .page-header h1 {{ | |
| font-size: 3rem; | |
| font-weight: 800; | |
| margin-bottom: 1rem; | |
| background: linear-gradient(135deg, #fff, #e2e8f0); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| }} | |
| .page-header p {{ | |
| font-size: 1.2rem; | |
| color: var(--gray-light); | |
| max-width: 600px; | |
| margin: 0 auto; | |
| margin-top:-20px | |
| }} | |
| /* Predictor Form */ | |
| /* Streamlit Help Text Overrides */ | |
| .st-cg, .st-cr {{ | |
| font-size: 0.8rem; | |
| color: var(--gray-light); | |
| margin-top: 0.25rem; | |
| }} | |
| .predict-btn-custom {{ /* Custom class to be used by st.button */ | |
| background: var(--gradient-accent) !important; | |
| color: var(--white) !important; | |
| padding: 1.25rem 3rem !important; | |
| border: none !important; | |
| border-radius: 50px !important; | |
| font-size: 1.1rem !important; | |
| font-weight: 700 !important; | |
| cursor: pointer !important; | |
| transition: all 0.3s ease !important; | |
| display: block !important; | |
| margin: 2rem auto !important; | |
| text-transform: uppercase !important; | |
| letter-spacing: 1px !important; | |
| box-shadow: var(--shadow-md) !important; | |
| position: relative !important; | |
| overflow: hidden !important; | |
| }} | |
| .predict-btn-custom:hover {{ | |
| transform: translateY(-3px) !important; | |
| box-shadow: var(--shadow-lg) !important; | |
| }} | |
| .predict-btn-custom::before {{ | |
| content: ''; | |
| position: absolute; | |
| top: 0; | |
| left: -100%; | |
| width: 100%; | |
| height: 100%; | |
| background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent); | |
| transition: left 0.5s; | |
| }} | |
| .predict-btn-custom:hover::before {{ | |
| left: 100%; | |
| }} | |
| .result-card {{ | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(20px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 24px; | |
| padding: 3rem; | |
| text-align: center; | |
| transform: translateY(30px); | |
| transition: all 0.5s ease; | |
| }} | |
| .result-card.show {{ | |
| opacity: 1; | |
| transform: translateY(0); | |
| }} | |
| .result-amount {{ | |
| font-size: 3.5rem; | |
| font-weight: 900; | |
| background: var(--gradient-accent); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| margin-bottom: 1rem; | |
| animation: countUp 1s ease-out; | |
| }} | |
| /* Features Section */ | |
| .features-grid {{ | |
| display: grid; | |
| grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
| gap: 2rem; | |
| margin:25px; | |
| }} | |
| .feature-card {{ | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(20px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 24px; | |
| padding: 2.5rem; | |
| text-align: center; | |
| transition: all 0.3s ease; | |
| box-shadow: var(--shadow-sm); /* Default shadow */ | |
| }} | |
| .feature-card:hover {{ | |
| transform: translateY(-10px); | |
| box-shadow: var(--shadow-lg); | |
| }} | |
| .feature-icon {{ | |
| font-size: 3rem; | |
| background: var(--gradient-accent); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| margin-bottom: 1rem; | |
| }} | |
| .feature-card h3 {{ | |
| font-size: 1.5rem; | |
| font-weight: 700; | |
| margin-bottom: 1rem; | |
| color: var(--white); /* Ensure headings are visible */ | |
| }} | |
| /* About Section */ | |
| .about-content {{ | |
| display: grid; | |
| grid-template-columns: 1fr 1fr; | |
| gap: 4rem; | |
| align-items: center; | |
| margin:30px; | |
| }} | |
| .about-text h2 {{ | |
| font-size: 2.5rem; | |
| font-weight: 800; | |
| margin-bottom: 1.5rem; | |
| background: linear-gradient(135deg, #fff, #e2e8f0); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| }} | |
| .about-text p {{ | |
| margin-bottom: 1.5rem; | |
| color: var(--gray-light); | |
| font-size: 1.1rem; | |
| }} | |
| .stats-grid {{ | |
| display: grid; | |
| grid-template-columns: repeat(2, 1fr); | |
| gap: 2rem; | |
| margin-top: 3rem; | |
| }} | |
| .stat-card {{ | |
| text-align: center; | |
| padding: 2rem; | |
| background: var(--glass-bg); | |
| border-radius: 16px; | |
| box-shadow: var(--shadow-sm); | |
| }} | |
| .stat-number {{ | |
| font-size: 2.5rem; | |
| font-weight: 900; | |
| background: var(--gradient-accent); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| background-clip: text; | |
| }} | |
| /* Contact Section */ | |
| [class*="st-key-contact-form"]{{ | |
| background: var(--glass-bg); | |
| backdrop-filter: blur(20px); | |
| border: 1px solid var(--glass-border); | |
| border-radius: 24px; | |
| padding: 0.5rem; | |
| max-width: 800px; | |
| margin: 0 auto; | |
| margin-top:-680px; | |
| max-height:400px !important; | |
| }} | |
| /* Loading Animation */ | |
| .loading {{ | |
| display: none; /* Controlled by Streamlit's session state */ | |
| text-align: center; | |
| padding: 2rem; | |
| }} | |
| .loading.show {{ | |
| display: block; | |
| }} | |
| .spinner {{ | |
| width: 40px; | |
| height: 40px; | |
| border: 3px solid rgba(255, 255, 255, 0.3); | |
| border-top: 3px solid var(--secondary); | |
| border-radius: 50%; | |
| animation: spin 1s linear infinite; | |
| margin: 0 auto 1rem; | |
| }} | |
| @keyframes spin {{ | |
| 0% {{ transform: rotate(0deg); }} | |
| 100% {{ transform: rotate(360deg); }} | |
| }} | |
| /* Responsive Design */ | |
| @media (max-width: 768px) {{ | |
| .mobile-menu-btn {{ | |
| display: block; | |
| }} | |
| .nav-menu {{ | |
| position: fixed; | |
| top: 80px; | |
| left: -100%; | |
| width: 100%; | |
| height: calc(100vh - 80px); | |
| background: var(--dark); | |
| flex-direction: column; | |
| justify-content: center; | |
| transition: left 0.3s ease; | |
| }} | |
| .nav-menu.active {{ | |
| left: 0; | |
| }} | |
| .hero-container {{ | |
| grid-template-columns: 1fr; | |
| text-align: center; | |
| padding-top: 2rem; /* Adjust padding for mobile hero */ | |
| }} | |
| .hero-visual {{ | |
| height: auto; /* Allow height to adjust */ | |
| margin-top: 2rem; | |
| }} | |
| .hero-card {{ | |
| position: static; /* Remove absolute positioning on mobile */ | |
| width: 100%; | |
| margin-bottom: 1.5rem; | |
| animation: none; /* Disable float animation on mobile */ | |
| }} | |
| .page {{ | |
| padding: 100px 0 60px; /* Adjust page padding for mobile */ | |
| }} | |
| .header h1, .page-header h1 {{ | |
| font-size: 2.5rem; | |
| }} | |
| .header .icon {{ | |
| font-size: 3rem; | |
| }} | |
| .main-form, .predictor-form, .contact-form {{ | |
| padding: 2rem; | |
| border-radius: 24px; | |
| }} | |
| .input-grid, .form-grid {{ | |
| grid-template-columns: 1fr; | |
| gap: 1.5rem; | |
| }} | |
| .result-amount {{ | |
| font-size: 2.5rem; | |
| }} | |
| .about-content, .footer-content {{ | |
| grid-template-columns: 1fr; | |
| }} | |
| .stats-grid {{ | |
| grid-template-columns: 1fr; | |
| }} | |
| }} | |
| /* Streamlit Specific Overrides */ | |
| /* Hide Streamlit's default header/footer elements */ | |
| footer {{ visibility: hidden; height: 0; overflow: hidden; }} /* Hides Streamlit's "Made with Streamlit" */ | |
| #MainMenu {{ visibility: hidden; }} /* Hides Streamlit's main menu icon */ | |
| .css-vk325g {{ /* Targets the header elements generated by Streamlit */ | |
| display: none !important; | |
| }} | |
| </style> | |
| </head> | |
| <body> | |
| <div class="bg-animation"></div> | |
| <div class="floating-shapes"> | |
| <div class="shape"></div> | |
| <div class="shape"></div> | |
| <div class="shape"></div> | |
| </div> | |
| <!-- Navigation --> | |
| <nav class="navbar" id="navbar"> | |
| <div class="nav-container"> | |
| <a href="#" class="logo" onclick="showPage('home')">CreditIQ</a> | |
| """,unsafe_allow_html=True) | |
| nav_cols = st.columns([5, 0.5, 0.5, 0.5, 0.5, 1]) | |
| with nav_cols[0]: | |
| st.markdown('<p class="logo">CreditIQ</p>', unsafe_allow_html=True) | |
| nav_items = ["home", "predictor", "features", "about", "contact"] | |
| for i, item in enumerate(nav_items): | |
| with nav_cols[i+1]: | |
| active = "active" if st.session_state.active_page == item else "" | |
| # Each button click updates the session state and triggers a rerun | |
| if st.button(item, key=f"nav_{item}_{st.session_state.active_page}", use_container_width=True): | |
| st.session_state.active_page = item | |
| st.session_state.show_prediction = False # Reset prediction display | |
| st.rerun() | |
| # JavaScript to apply the correct CSS classes to the Streamlit buttons | |
| st.markdown(""" | |
| <script> | |
| const buttons = window.parent.document.querySelectorAll('.stButton button'); | |
| const activePage = '""" + st.session_state.active_page + """'; | |
| buttons.forEach(button => { | |
| const buttonText = button.innerText; | |
| if (["Home", "Predictor", "Features", "About", "Contact"].includes(buttonText)) { | |
| button.classList.add('nav-button'); | |
| if (buttonText === activePage) { | |
| button.classList.add('active'); | |
| } | |
| } | |
| }); | |
| </script> | |
| """, unsafe_allow_html=True) | |
| st.markdown(f""" | |
| </div> | |
| </nav> | |
| <!-- Content Pages (managed by Streamlit Python logic) --> | |
| <div id="streamlit_content_container"> | |
| <!-- Streamlit will inject its components here, corresponding to active_page --> | |
| </div> | |
| <!-- This part of the HTML is only for the footer, as Streamlit manages the main content --> | |
| <footer class="app-footer"> | |
| <div class="footer-content"> | |
| <div class="footer-section"> | |
| <h3>CreditIQ</h3> | |
| <p style="color: var(--gray-light); font-size: 0.9rem;">Your trusted AI partner for credit expenditure forecasting. Empowering financial decisions.</p> | |
| </div> | |
| <div class="footer-section"> | |
| <h3>Quick Links</h3> | |
| <ul> | |
| <li><a href="#" onclick="showPage('home')">Home</a></li> | |
| <li><a href="#" onclick="showPage('predictor')">Predictor</a></li> | |
| <li><a href="#" onclick="showPage('features')">Features</a></li> | |
| <li><a href="#" onclick="showPage('about')">About</a></li> | |
| </ul> | |
| </div> | |
| <div class="footer-section"> | |
| <h3>Contact Us</h3> | |
| <p style="color: var(--gray-light);"><i class="fas fa-envelope"></i> info@creditiq.com</p> | |
| <p style="color: var(--gray-light);"><i class="fas fa-phone"></i> +1 (123) 456-7890</p> | |
| </div> | |
| <div class="footer-section"> | |
| <h3>Follow Us</h3> | |
| <ul style="display: flex; gap: 1rem;"> | |
| <li><a href="#" style="font-size: 1.2rem;"><i class="fab fa-facebook-f"></i></a></li> | |
| <li><a href="#" style="font-size: 1.2rem;"><i class="fab fa-twitter"></i></a></li> | |
| <li><a href="#" style="font-size: 1.2rem;"><i class="fab fa-linkedin-in"></i></a></li> | |
| <li><a href="#" style="font-size: 1.2rem;"><i class="fab fa-instagram"></i></a></li> | |
| </ul> | |
| </div> | |
| </div> | |
| <div class="footer-bottom"> | |
| © 2023 CreditIQ. All rights reserved. | |
| </div> | |
| </footer> | |
| </body> | |
| </html> | |
| """, unsafe_allow_html=True) | |
| st.markdown(""" | |
| <style> | |
| :root { | |
| --primary-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| --secondary-gradient: linear-gradient(135deg, #f093fb 0%, #f5576c 100%); | |
| --accent-gradient: linear-gradient(135deg, #4facfe 0%, #00f2fe 100%); | |
| --dark-gradient: linear-gradient(135deg, #0c0c0c 0%, #1a1a1a 100%); | |
| --glass-bg: rgba(255, 255, 255, 0.1); | |
| --glass-border: rgba(255, 255, 255, 0.2); | |
| --shadow-medium: 0 16px 64px rgba(0, 0, 0, 0.15); | |
| --shadow-strong: 0 24px 96px rgba(0, 0, 0, 0.2); | |
| } | |
| .bg-animation { | |
| position: fixed; top: 0; left: 0; | |
| width: 100%; height: 100%; z-index: -2; | |
| background: linear-gradient(45deg, #667eea, #764ba2, #f093fb, #f5576c, #4facfe, #00f2fe); | |
| background-size: 400% 400%; animation: gradientShift 15s ease infinite; | |
| } | |
| @keyframes gradientShift { 0% {background-position: 0% 50%;} 50% {background-position: 100% 50%;} 100% {background-position: 0% 50%;} } | |
| .floating-shapes { | |
| position: fixed; top: 0; left: 0; | |
| width: 100%; height: 100%; z-index: -1; pointer-events: none; | |
| } | |
| .shape { position: absolute; opacity: 0.1; animation: float 20s infinite ease-in-out; } | |
| .shape:nth-child(1) { top: 10%; left: 10%; width: 80px; height: 80px; background: var(--accent-gradient); border-radius: 50%; } | |
| .shape:nth-child(2) { top: 70%; right: 10%; width: 120px; height: 120px; background: var(--secondary-gradient); border-radius: 30% 70% 70% 30% / 30% 30% 70% 70%; animation-delay: 5s; } | |
| .shape:nth-child(3) { bottom: 20%; left: 20%; width: 100px; height: 100px; background: var(--primary-gradient); border-radius: 20px; transform: rotate(45deg); animation-delay: 10s; } | |
| @keyframes float { 0%, 100% {transform: translateY(0px) rotate(0deg);} 33% {transform: translateY(-30px) rotate(120deg);} 66% {transform: translateY(15px) rotate(240deg);} } | |
| /* Header and Form Styling */ | |
| .header { text-align: center; margin-bottom: 3rem; } | |
| .header h1 { font-size: 3.5rem; font-weight: 900; background: linear-gradient(135deg, #fff, #f0f0f0); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 1rem; } | |
| .header .icon { font-size: 4rem; margin-bottom: 1rem; background: var(--accent-gradient); -webkit-background-clip: text; -webkit-text-fill-color: transparent; } | |
| .header p { font-size: 1.2rem; color: rgba(255, 255, 255, 0.8); max-width: 600px; margin: 0 auto; } | |
| .section-title { | |
| font-size: 1.8rem; | |
| font-weight: 700; | |
| margin-bottom: 2rem; | |
| text-align: center; | |
| background: linear-gradient(135deg, #fff, #f0f0f0); | |
| -webkit-background-clip: text; | |
| -webkit-text-fill-color: transparent; | |
| font-family:time new roman !important; | |
| } | |
| /* Styling Streamlit Widgets to Match Your Design */ | |
| .stTextInput label, .stNumberInput label, .stSelectbox label { | |
| font-weight: 500; margin-bottom: 0.5rem; color: rgba(255, 255, 255, 0.9); | |
| font-size: 0.9rem; text-transform: uppercase; letter-spacing: 0.5px; | |
| font-family:time new roman !important; | |
| } | |
| .stTextInput label > div > p, .stNumberInput label > div > p , .stSelectbox label > div > p { | |
| font-family:time new roman !important; | |
| } | |
| .stTextInput input, .stNumberInput input{ | |
| width: 100%; padding: 1rem 1.25rem; | |
| background: rgba(255, 255, 255, 0.1) !important; | |
| border: 1px solid rgba(255, 255, 255, 0.2) !important; | |
| border-radius: 16px !important; color: #004cff !important; | |
| font-size: 1rem !important; transition: all 0.3s ease !important; | |
| backdrop-filter: blur(10px) !important; | |
| font-family:time new roman !important; | |
| } | |
| .stSelectbox div[data-baseweb="select"] > div { | |
| font-family:time new roman !important; | |
| } | |
| .stForm [data-testid="stFormSubmitButton"] button > div > p { | |
| font-family:time new roman !important; | |
| } | |
| .stForm [data-testid="stFormSubmitButton"] button { | |
| background: var(--accent-gradient); border: none; padding: 1.25rem 3rem; | |
| border-radius: 50px; color: white; font-size: 1.1rem; | |
| font-weight: 700; cursor: pointer; transition: all 0.3s ease; | |
| text-transform: uppercase; letter-spacing: 1px; | |
| box-shadow: var(--shadow-medium); display: block; margin: 2rem auto; | |
| font-family:time new roman !important; | |
| height:60px; | |
| text-align:center; | |
| margin-top:-3px; | |
| } | |
| .stForm [data-testid="stFormSubmitButton"] button:hover { | |
| transform: translateY(-3px); box-shadow: var(--shadow-strong); | |
| font-family:time new roman !important; | |
| } | |
| [class*="st-key-pred"] >div >button >div >p { | |
| text-decoration: underline; | |
| color:var(--primary); | |
| width:200px; | |
| font-weight:bold; | |
| } | |
| [class*="st-key-pred"]>div >button:active { | |
| background:transparent !important; | |
| } | |
| [class*="st-key-abt"] >div >button >div >p { | |
| text-decoration: underline; | |
| color:var(--primary); | |
| width:200px; | |
| font-weight:bold; | |
| } | |
| [class*="st-key-abt"]>div >button:active { | |
| background:transparent !important; | |
| } | |
| [class*="st-key-navbtn"] { | |
| display: flex; | |
| gap: 1rem; | |
| z-index:100000000; | |
| margin-top:-330px; | |
| flex-wrap: wrap; | |
| margin-left:200px; | |
| } | |
| [class*="st-key-abt"] { | |
| background: transparent; | |
| color: var(--white); | |
| padding: 1rem 2rem; | |
| border: 2px solid var(--glass-border); | |
| border-radius: 50px; | |
| text-decoration: none; | |
| font-weight: 600; | |
| transition: all 0.3s ease; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| width:185px; | |
| margin-left:220px; | |
| height:60px; | |
| margin-top:-74px; | |
| } | |
| [class*="st-key-pred"] { | |
| background: var(--gradient-accent); | |
| color: var(--white); | |
| padding: 1rem 2rem; | |
| border-radius: 50px; | |
| text-decoration: none; | |
| font-weight: 600; | |
| transition: all 0.3s ease; | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.5rem; | |
| box-shadow: var(--shadow-md); | |
| width:200px; | |
| height:60px; | |
| } | |
| [class*="st-key-pred"] :hover { | |
| transform: translateY(-3px); box-shadow: var(--shadow-strong); | |
| font-family:time new roman !important; | |
| } | |
| /* Result Card */ | |
| .result-card { | |
| background: var(--glass-bg); backdrop-filter: blur(20px); | |
| border: 1px solid var(--glass-border); border-radius: 24px; | |
| padding: 2.5rem; margin-top: 2rem; text-align: center; | |
| box-shadow: var(--shadow-medium); | |
| } | |
| .result-amount { font-size: 3rem; font-weight: 900; background: var(--accent-gradient); -webkit-background-clip: text; -webkit-text-fill-color: transparent; margin-bottom: 1rem; } | |
| .result-label { font-size: 1.2rem; color: rgba(255, 255, 255, 0.8); margin-bottom: 1rem; } | |
| button[kind="secondary"] { | |
| position: relative !important; | |
| } | |
| button[kind="secondary"]:hover,button[kind="secondary"]:active { | |
| color: var(--white) !important; | |
| } | |
| button[kind="secondary"]:active { | |
| background: linear-gradient(to right, #4f46e5, #9333ea); | |
| } | |
| [class*="st-key-main-form"]{ | |
| background: var(--glass-bg); backdrop-filter: blur(20px); | |
| border: 1px solid var(--glass-border); border-radius: 32px; | |
| padding: 3rem; box-shadow: var(--shadow-strong); | |
| width:60%; | |
| align-self: center; | |
| color:blue; | |
| max-height:520px; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # --- Load the trained model --- | |
| def load_model(): | |
| try: | |
| model = joblib.load('credit_card_expenditure_model.joblib') | |
| return model | |
| except FileNotFoundError: | |
| st.error("Model file 'credit_card_expenditure_model.joblib' not found. Please ensure it's in the same directory as this app.") | |
| st.stop() # Stop the app if model is not found | |
| except Exception as e: | |
| st.error(f"Error loading model: {e}") | |
| st.stop() | |
| # --- Streamlit Content Injection --- | |
| # This section uses st.empty() to create a placeholder where our content | |
| # for the active page will be rendered. | |
| streamlit_content_placeholder = st.empty() | |
| # --- Page Rendering Logic based on active_page state --- | |
| with streamlit_content_placeholder.container(): | |
| # Home Page | |
| if st.session_state.active_page == 'home': | |
| st.markdown(f""" | |
| <div id="home" class="page active"> | |
| <section class="hero"> | |
| <div class="hero-bg"></div> | |
| <div class="hero-container"> | |
| <div class="hero-content"> | |
| <h1>Predict Credit <span class="highlight">Expenditure</span> with AI</h1> | |
| <p>Harness the power of advanced machine learning to accurately forecast credit card spending patterns and make informed financial decisions.</p> | |
| </div> | |
| <div class="hero-visual"> | |
| <div class="hero-card"> | |
| <i class="fas fa-brain" style="font-size: 2rem; color: #4facfe; margin-bottom: 1rem;"></i> | |
| <h3>AI-Powered</h3> | |
| <p>Advanced algorithms analyze spending patterns</p> | |
| </div> | |
| <div class="hero-card"> | |
| <i class="fas fa-shield-alt" style="font-size: 2rem; color: #10B981; margin-bottom: 1rem;"></i> | |
| <h3>Secure</h3> | |
| <p>Bank-level security for your data</p> | |
| </div> | |
| <div class="hero-card"> | |
| <i class="fas fa-bolt" style="font-size: 2rem; color: #F59E0B; margin-bottom: 1rem;"></i> | |
| <h3>Fast</h3> | |
| <p>Instant predictions in seconds</p> | |
| </div> | |
| </div> | |
| </div> | |
| </section> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with st.container(key="navbtn"): | |
| if st.button(" Start Predicting",key="pred"): | |
| st.session_state.active_page = 'predictor' | |
| st.rerun() | |
| if st.button(" Learn More",key="abt"): | |
| st.session_state.active_page = 'about' | |
| st.rerun() | |
| # We need to trigger the JS function to set active state and navigate | |
| elif st.session_state.active_page == 'predictor': | |
| # --- Prediction Form --- | |
| # We use st.form to group all the inputs. When the submit button is pressed, | |
| # Streamlit re-runs the script with all the new input values. | |
| with st.container(key ="main-form" ): | |
| st.markdown('<h2 class="section-title">Customer Financial Profile</h2>', unsafe_allow_html=True) | |
| with st.form(key="prediction_form"): | |
| # Create columns for the input grid layout | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| reports = st.number_input("Major Derogatory Reports", min_value=0, max_value=20, value=0, help="Number of serious credit issues reported") | |
| age = st.number_input("Age (years)", min_value=18.0, max_value=100.0, value=30.0, step=0.1, help="Customer's age in years") | |
| income = st.number_input("Yearly Income ($10,000s)", min_value=0.0, max_value=100.0, value=3.0, step=0.1, help="Annual income in tens of thousands") | |
| owner = st.selectbox("Home Owner", ('no', 'yes'), help="Does customer own their home?") | |
| with col2: | |
| card = st.selectbox("Card Owner", ('no', 'yes'), help="Does customer own a credit card?") | |
| share = st.number_input("Monthly Expenditure Ratio", min_value=0.0, max_value=1.0, value=0.1, step=0.01, help="Ratio of monthly spending to yearly income") | |
| active = st.number_input("Active Credit Accounts", min_value=0, max_value=50, value=5, help="Total number of active credit accounts") | |
| selfemp = st.selectbox("Self Employed", ('no', 'yes'), help="Is the customer self-employed?") | |
| with col3: | |
| dependents = st.number_input("Number of Dependents", min_value=0, max_value=10, value=0, help="Financially dependent individuals") | |
| months = st.number_input("Months at Current Address", min_value=0, max_value=500, value=36, help="Duration at current residence") | |
| majorcards = st.number_input("Major Credit Cards", min_value=0, max_value=10, value=1, help="Number of major credit cards owned") | |
| payments = st.number_input("Credit Card Payments", min_value=0, max_value=50, value=6, help="Total credit card payments made") | |
| # The submit button for the form | |
| submitted = st.form_submit_button("Predict Expenditure") | |
| # --- Model Prediction Logic --- | |
| # This block runs only when the form has been submitted. | |
| if st.button("Dismiss modal", key="dismiss_modal_btn", help="Hidden dismiss button"): | |
| st.session_state.show_prediction = False | |
| st.rerun() | |
| if submitted: | |
| model = load_model() | |
| if model is not None: | |
| # Show a loading spinner while processing | |
| with st.spinner("Analyzing financial data with AI..."): | |
| time.sleep(1) # Simulate processing time | |
| # Convert categorical inputs from 'yes'/'no' to 1/0 for the model | |
| owner_encoded = 1 if owner == 'yes' else 0 | |
| card_encoded = 1 if card == 'yes' else 0 | |
| selfemp_encoded = 1 if selfemp == 'yes' else 0 | |
| # Create a pandas DataFrame with the exact structure the model expects | |
| input_data = pd.DataFrame([{ | |
| 'card': card, # "yes"/"no" as string | |
| 'reports': reports, # int | |
| 'age': age, # float | |
| 'income': income, # float | |
| 'share': share, # float | |
| 'owner': owner, # "yes"/"no" as string | |
| 'selfemp': selfemp, # "yes"/"no" as string | |
| 'dependents': dependents, # int | |
| 'months': months, # int | |
| 'majorcards': majorcards, | |
| 'active':active# int | |
| # float or placeholder if unknown | |
| }]) | |
| expected_features = model.feature_names_in_ | |
| # Filter and reorder the input columns to match the model | |
| input_filtered = input_data[expected_features] | |
| print("input_data",input_data) | |
| print("expected",model.feature_names_in_) # If using scikit-learn 1.0+ | |
| print("input_data_type",input_data.dtypes) | |
| try: | |
| # Get the prediction from the model | |
| prediction = model.predict(input_filtered)[0] | |
| print("prediction:",prediction) | |
| # Store the result and set the flag to show it | |
| st.session_state.predicted_value = abs(prediction) # Ensure it's a positive number | |
| st.session_state.show_prediction = True | |
| except Exception as e: | |
| st.error(f"Could not make a prediction. Error: {e}") | |
| else: | |
| st.error("The prediction model is not available. Please check server logs.") | |
| # --- Display Prediction Result --- | |
| # This block displays the result card if a prediction has been made. | |
| if st.session_state.show_prediction: | |
| st.markdown(f""" | |
| <style> | |
| /* Modal overlay */ | |
| .modal-overlay {{ | |
| position: fixed; | |
| top: 0; left: 0; right: 0; bottom: 0; | |
| background: rgba(0,0,0,0.6); | |
| display: flex; | |
| justify-content: center; | |
| align-items: center; | |
| z-index: 9999; | |
| }} | |
| /* Modal content */ | |
| .modal-content {{ | |
| background: #222; | |
| padding: 2rem 3rem; | |
| border-radius: 10px; | |
| color: white; | |
| max-width: 400px; | |
| box-shadow: 0 0 15px rgba(0,0,0,0.5); | |
| text-align: center; | |
| position: relative; | |
| }} | |
| .result-label {{ | |
| font-size: 1.2rem; | |
| font-weight: 600; | |
| margin-bottom: 0.5rem; | |
| }} | |
| .result-amount {{ | |
| font-size: 2.5rem; | |
| font-weight: 700; | |
| margin-bottom: 1rem; | |
| }} | |
| </style> | |
| <div class="modal-overlay" id="modal-overlay"> | |
| <div class="modal-content" id="modal-content"> | |
| <div class="result-label">Predicted Monthly Expenditure</div> | |
| <div class="result-amount">{st.session_state.predicted_value:,.2f}</div> | |
| <p style="color: rgba(255, 255, 255, 0.7); margin-top: 1rem;"> | |
| Based on advanced machine learning analysis of financial patterns. | |
| </p> | |
| </div> | |
| </div> | |
| """, | |
| unsafe_allow_html=True, | |
| ) | |
| my_js = """ | |
| // Close modal if clicking outside the modal-content | |
| const overlay = window.parent.document.getElementById("modal-overlay"); | |
| overlay.addEventListener("click", function(e) {{ | |
| if (e.target.id === "modal-overlay") {{ | |
| const btn = window.parent.document.querySelector('[class*="st-key-dismiss_modal_btn"]>div >div >div >div >button'); | |
| if (btn) { | |
| btn.click(); | |
| } | |
| //overlay.style.display = "none"; | |
| }} | |
| }}); | |
| """ | |
| my_html = f"<script>{my_js}</script>" | |
| html(my_html) | |
| # Features Page | |
| elif st.session_state.active_page == 'features': | |
| st.markdown(""" | |
| <div id="features" class="page active"> | |
| <div class="container"> | |
| <div class="page-header"> | |
| <h1>Powerful Features</h1> | |
| <p>Discover what makes CreditIQ your ideal partner for financial insights.</p> | |
| </div> | |
| <div class="features-grid"> | |
| <div class="feature-card"> | |
| <i class="fas fa-chart-area feature-icon"></i> | |
| <h3>Accurate Predictions</h3> | |
| <p style="color: var(--gray-light);">Leverage state-of-the-art machine learning models for highly precise expenditure forecasts.</p> | |
| </div> | |
| <div class="feature-card"> | |
| <i class="fas fa-database feature-icon"></i> | |
| <h3>Data Security</h3> | |
| <p style="color: var(--gray-light);">Your financial data is protected with industry-leading encryption and security protocols.</p> | |
| </div> | |
| <div class="feature-card"> | |
| <i class="fas fa-user-shield feature-icon"></i> | |
| <h3>Privacy Focused</h3> | |
| <p style="color: var(--gray-light);">We prioritize your privacy with strict data handling and anonymity measures.</p> | |
| </div> | |
| <div class="feature-card"> | |
| <i class="fas fa-mobile-alt feature-icon"></i> | |
| <h3>Responsive Design</h3> | |
| <p style="color: var(--gray-light);">Access CreditIQ seamlessly on any device, from desktop to mobile.</p> | |
| </div> | |
| <div class="feature-card"> | |
| <i class="fas fa-lightbulb feature-icon"></i> | |
| <h3>Actionable Insights</h3> | |
| <p style="color: var(--gray-light);">Understand your spending habits and gain insights to optimize your finances.</p> | |
| </div> | |
| <div class="feature-card"> | |
| <i class="fas fa-cogs feature-icon"></i> | |
| <h3>Customizable Models</h3> | |
| <p style="color: var(--gray-light);">Tailor prediction models to fit unique financial scenarios and individual needs.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # About Page | |
| elif st.session_state.active_page == 'about': | |
| st.markdown(""" | |
| <div id="about" class="page active"> | |
| <div class="container"> | |
| <div class="page-header"> | |
| <h1>About CreditIQ</h1> | |
| <p>Our mission is to empower individuals and businesses with intelligent financial forecasting tools.</p> | |
| </div> | |
| <div class="about-content"> | |
| <div class="about-text"> | |
| <h2>Revolutionizing Financial Forecasting</h2> | |
| <p>CreditIQ was founded on the principle that informed financial decisions lead to greater stability and growth. We believe that by providing highly accurate, AI-driven credit expenditure predictions, we can help our users better manage their budgets, identify trends, and plan for the future with confidence.</p> | |
| <p>Our team of data scientists and financial experts has developed a robust platform that combines cutting-edge machine learning algorithms with user-friendly design. We are committed to continuous innovation and maintaining the highest standards of data security and privacy.</p> | |
| <div class="stats-grid"> | |
| <div class="stat-card"> | |
| <div class="stat-number">99%</div> | |
| <div style="color: var(--gray-light);">Accuracy Rate</div> | |
| </div> | |
| <div class="stat-card"> | |
| <div class="stat-number">1M+</div> | |
| <div style="color: var(--gray-light);">Predictions Made</div> | |
| </div> | |
| </div> | |
| </div> | |
| <div class="about-visual"> | |
| <!-- Placeholder for an image or animated visual if desired --> | |
| <img src="https://placehold.co/400x300/0c0c0c/1a1a1a?text=AI+Financials" alt="AI Financial Illustration" style="max-width: 100%; height: auto; border-radius: 16px; box-shadow: var(--shadow-md);"> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| st.markdown(f"<script>showPage('about');</script>", unsafe_allow_html=True) | |
| # Contact Page | |
| elif st.session_state.active_page == 'contact': | |
| st.markdown(""" | |
| <div id="contact" class="page active"> | |
| <div class="container"> | |
| <div class="page-header"> | |
| <h1>Get in Touch</h1> | |
| <p>Have questions, feedback, or need support? We're here to help.</p> | |
| </div> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Inject Streamlit components into the Contact form | |
| with st.container(key="contact-form"): | |
| with st.form("contact_form",clear_on_submit=True): | |
| st.text_input("Your Name", key="contact_name_input", help="Please enter your name.") | |
| st.text_input("Your Email", key="contact_email_input", help="Please enter your email address.") | |
| st.text_area("Message", key="contact_message_input", help="Type your message here.") | |
| submittedcon = st.form_submit_button("Send Message", help="Click to send your message.") | |
| if submittedcon : | |
| st.success("Thank you for your message! We will get back to you soon.") | |