import streamlit as st import pandas as pd import re from datetime import datetime from typing import List # Page configuration st.set_page_config( page_title="Scholarship Search (Context Based Search)", page_icon="🎓", layout="wide" ) # Load and prepare data @st.cache_data def load_scholarships(): try: df = pd.read_csv("scholarships_data.csv", quotechar='"', quoting=1) df = df.map(lambda x: x.strip() if isinstance(x, str) else x) df.rename(columns=lambda x: x.strip(), inplace=True) return df except Exception as e: st.error(f"Error loading data: {str(e)}") st.stop() # Custom CSS for styling def load_css(): st.markdown(""" """, unsafe_allow_html=True) # Format the deadline status def format_deadline(deadline_str): try: if not deadline_str or pd.isna(deadline_str) or deadline_str == "N/A": return "Open - No specific deadline", "#00b894" # Handle different date formats try: deadline = datetime.strptime(deadline_str, "%d-%m-%Y") except ValueError: try: deadline = datetime.strptime(deadline_str, "%Y-%m-%d") except ValueError: return deadline_str, "#00b894" today = datetime.now() days_left = (deadline - today).days if days_left < 0: return "Expired", "#e74c3c" elif days_left <= 7: return f"{days_left} days left!", "#ff7675" elif days_left <= 30: return f"{days_left} days left", "#00b894" else: return f"{days_left} days left", "#3498db" except: return deadline_str, "#00b894" # Highlight search terms in text def highlight_text(text, search_terms): if not search_terms or not text: return text # Convert search terms to a list if it's a string if isinstance(search_terms, str): search_terms = [search_terms] # Highlight each search term for term in search_terms: if term.strip(): pattern = re.compile(re.escape(term.strip()), re.IGNORECASE) text = pattern.sub(f'{term}', text) return text # Display scholarship results def display_scholarships(df: pd.DataFrame, search_terms: List[str] = None) -> None: if df.empty: st.markdown('
No scholarships found. Try a different search term.
', unsafe_allow_html=True) return st.markdown(f"
Found {len(df)} scholarships
", unsafe_allow_html=True) for _, row in df.iterrows(): name = row['Scholarship Name'] eligibility = row['Eligibility'] deadline = row['Deadline'] if 'Deadline' in row else "" link = row['Link'] # Format deadline text and color deadline_text, deadline_color = format_deadline(deadline) # Highlight search terms if provided if search_terms: name = highlight_text(name, search_terms) eligibility = highlight_text(eligibility, search_terms) # Generate the scholarship card scholarship_html = f"""
{name}
⏰ {deadline_text}
{eligibility}
Apply Now
""" st.markdown(scholarship_html, unsafe_allow_html=True) # App header def display_header(): st.markdown("""

🎓 Scholarship Search

""", unsafe_allow_html=True) # Simplified search function def search_scholarships(df: pd.DataFrame, query: str) -> pd.DataFrame: if not query: return df.head(10) search_terms = query.split() filtered_df = df.copy() for term in search_terms: if term.strip(): filtered_df = filtered_df[ filtered_df['Scholarship Name'].str.contains(term, case=False, na=False) | filtered_df['Eligibility'].str.contains(term, case=False, na=False) ] return filtered_df.head(15) # Main function def main(): # Load custom CSS load_css() # Load scholarship data df = load_scholarships() # Display header display_header() # Search container st.markdown('
', unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) # Create a layout with a text input and a button side by side col1, col2 = st.columns([5, 1]) with col1: search_term = st.text_input("", placeholder="🔍 Search for scholarships (e.g., 'engineering scholarships')") with col2: st.markdown("
", unsafe_allow_html=True) search_button = st.button("Search") st.markdown("
", unsafe_allow_html=True) # Example queries example_queries = [ "undergraduate scholarships", "engineering scholarships", "international scholarships", "research fellowships" ] # Display example queries st.markdown("
Try: " + " | ".join([f"{query}" for query in example_queries]) + "
", unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) st.markdown('
', unsafe_allow_html=True) # Results container st.markdown('
', unsafe_allow_html=True) # Process search if search_button or search_term: with st.spinner("Searching for scholarships..."): results_df = search_scholarships(df, search_term) display_scholarships(results_df, search_term.split()) else: # Display initial scholarships display_scholarships(df.head(10)) st.markdown('
', unsafe_allow_html=True) if __name__ == "__main__": main()