import streamlit as st
import pandas as pd
import pickle
import os
import warnings
warnings.filterwarnings("ignore")
# ──────────────────────────────────────────────
# PAGE CONFIG
# ──────────────────────────────────────────────
st.set_page_config(
page_title="House Price AI",
page_icon="🏠",
layout="centered",
initial_sidebar_state="auto",
)
# ──────────────────────────────────────────────
# CSS LOADER ← reads from static/css/style.css
# ──────────────────────────────────────────────
def load_css():
"""
Reads the external stylesheet from static/css/style.css
and injects it into the Streamlit page via st.markdown.
All visual styling lives in that file — app.py stays clean.
"""
css_path = os.path.join("static", "css", "style.css")
if not os.path.exists(css_path):
st.warning("⚠️ style.css not found — place it at static/css/style.css")
return
with open(css_path, "r", encoding="utf-8") as f:
css_content = f.read()
st.markdown(f"", unsafe_allow_html=True)
load_css()
# ──────────────────────────────────────────────
# DATA & MODEL
# ──────────────────────────────────────────────
DATA_PATH = "data_updated_ap_kakinada.csv"
MODEL_PATH = "model.pkl"
if not os.path.exists(DATA_PATH):
st.error("❌ Dataset file not found! Expected: data_updated_ap_kakinada.csv")
st.stop()
if not os.path.exists(MODEL_PATH):
st.error("❌ Model file not found! Expected: model.pkl")
st.stop()
df = pd.read_csv(DATA_PATH)
with open(MODEL_PATH, "rb") as f:
model = pickle.load(f)
# ──────────────────────────────────────────────
# SESSION STATE
# ──────────────────────────────────────────────
if "logged_in" not in st.session_state:
st.session_state.logged_in = False
if "username" not in st.session_state:
st.session_state.username = ""
# ──────────────────────────────────────────────
# HELPER: render HTML card wrapper
# ──────────────────────────────────────────────
def card_open(extra_class=""):
st.markdown(f'
", unsafe_allow_html=True)
# ──────────────────────────────────────────────
# PAGE: LOGIN
# ──────────────────────────────────────────────
def login():
# Hero header
st.markdown("""
AI-Powered · Real-time Estimates
Welcome Back
Sign in to your House Price AI account
""", unsafe_allow_html=True)
card_open()
username = st.text_input("Username", placeholder="Enter your username")
password = st.text_input("Password", type="password", placeholder="Enter your password")
if st.button("🔐 Sign In"):
if username and password:
st.session_state.logged_in = True
st.session_state.username = username
st.success("✅ Login successful! Redirecting…")
st.rerun()
else:
st.error("❌ Please enter both username and password.")
st.markdown("""
Don't have an account?
Use the sidebar → Signup
""", unsafe_allow_html=True)
card_close()
# ──────────────────────────────────────────────
# PAGE: SIGNUP
# ──────────────────────────────────────────────
def signup():
st.markdown("""
Create Account
Start predicting house prices in seconds
""", unsafe_allow_html=True)
card_open()
username = st.text_input("Username", placeholder="Choose a username")
password = st.text_input("Password", type="password", placeholder="Create a strong password")
confirm = st.text_input("Confirm Password", type="password", placeholder="Repeat your password")
if st.button("✨ Create Account"):
if not username or not password or not confirm:
st.error("❌ All fields are required.")
elif password != confirm:
st.error("❌ Passwords do not match.")
elif len(password) < 6:
st.warning("⚠️ Password should be at least 6 characters.")
else:
st.success("✅ Account created! Please log in.")
st.markdown("""
Already have an account?
Use the sidebar → Login
""", unsafe_allow_html=True)
card_close()
# ──────────────────────────────────────────────
# PAGE: DASHBOARD
# ──────────────────────────────────────────────
def dashboard():
# ── SIDEBAR ──────────────────────────────
with st.sidebar:
st.markdown("""
""", unsafe_allow_html=True)
st.markdown(f"""
{st.session_state.username[:1].upper() if st.session_state.username else "G"}
{st.session_state.username or "Guest"}
Signed in
""", unsafe_allow_html=True)
st.markdown("---")
if st.button("🚪 Sign Out"):
st.session_state.logged_in = False
st.session_state.username = ""
st.rerun()
# ── HERO ─────────────────────────────────
st.markdown(f"""
AI-Powered · Real-time Estimates
House Price
Predictor
Enter city and area details to get an instant AI-powered price estimate for any property.
""", unsafe_allow_html=True)
# ── STAT CARDS ───────────────────────────
col1, col2, col3 = st.columns(3)
with col1:
st.markdown("""
""", unsafe_allow_html=True)
with col2:
st.markdown("""
""", unsafe_allow_html=True)
with col3:
st.markdown("""
""", unsafe_allow_html=True)
st.markdown("
", unsafe_allow_html=True)
# ── PREDICT FORM ─────────────────────────
card_open()
st.markdown("""
📍 Get Price Estimate
Fill in the property details below
""", unsafe_allow_html=True)
cities = sorted(df["city"].unique()) if "city" in df.columns else ["Kakinada"]
city = st.selectbox("City", cities, help="Select the city where the property is located")
sqft = st.number_input(
"Area (sq ft)",
min_value=100.0,
max_value=50000.0,
step=50.0,
help="Enter the total built-up area in square feet",
)
predict_clicked = st.button("🔍 Predict Price")
card_close()
# ── RESULT ───────────────────────────────
if predict_clicked:
if sqft < 100:
st.error("❌ Please enter a valid area (minimum 100 sq ft).")
else:
try:
with st.spinner("Calculating estimate…"):
prediction = model.predict([[sqft]])[0]
price = round(prediction, 2)
price_sqft = round(price / sqft, 2)
card_open()
st.markdown(f"""
💰 Predicted Market Price
₹{price:,.2f}
Based on current market trends · {city}
📍 City
{city}
📐 Area
{sqft:,.0f} sq ft
📈 Price per sq ft
₹{price_sqft:,.2f}
""", unsafe_allow_html=True)
card_close()
except Exception as e:
st.error(f"❌ Prediction error: {e}")
# ── DATASET PREVIEW ──────────────────────
st.markdown("
", unsafe_allow_html=True)
card_open()
st.markdown("""
📊 Dataset Preview
Showing first 10 rows of the training data
""", unsafe_allow_html=True)
st.dataframe(df.head(10), use_container_width=True)
card_close()
# ──────────────────────────────────────────────
# ROUTING
# ──────────────────────────────────────────────
if st.session_state.logged_in:
dashboard()
else:
with st.sidebar:
st.markdown("""
""", unsafe_allow_html=True)
choice = st.selectbox("", ["Login", "Sign Up"], label_visibility="collapsed")
if choice == "Login":
login()
else:
signup()