Spaces:
Build error
Build error
| import os | |
| import streamlit as st | |
| import pandas as pd | |
| import google.generativeai as genai | |
| from google.generativeai.types import GenerationConfig | |
| import datetime | |
| import uuid | |
| import json | |
| import smtplib | |
| from email.mime.text import MIMEText | |
| from email.mime.multipart import MIMEMultipart | |
| # Configuration | |
| os.environ['GOOGLE_API_KEY'] = os.getenv('GOOGLE_API_KEY', 'your_key_here') | |
| genai.configure(api_key=os.environ['GOOGLE_API_KEY']) | |
| # Load and prepare 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() | |
| # Convert CSV to RAG context | |
| def create_rag_context(df): | |
| context = "Scholarship Database:\n\n" | |
| for _, row in df.iterrows(): | |
| context += f"""Scholarship Name: {row['Scholarship Name']} | |
| Eligibility: {row['Eligibility']} | |
| Deadline: {row['Deadline']} | |
| Link: {row['Link']}\n\n""" | |
| return context | |
| # Initialize Gemini model | |
| def get_rag_model(): | |
| return genai.GenerativeModel('gemini-1.5-pro') | |
| # Custom CSS for styling | |
| def load_css(): | |
| st.markdown(""" | |
| <style> | |
| /* Custom color for results */ | |
| .stMarkdown p, .stMarkdown ul, .stMarkdown ol { | |
| color: rgb(1, 27, 29); /* Custom color for results */ | |
| } | |
| /* Card styling */ | |
| .scholarship-card { | |
| background-color: #f8f9fa; | |
| border-radius: 10px; | |
| padding: 20px; | |
| margin-bottom: 20px; | |
| border-left: 5px solid #4CAF50; | |
| box-shadow: 0 4px 8px rgba(0,0,0,0.1); | |
| } | |
| /* Tabs styling */ | |
| .stTabs [data-baseweb="tab-list"] { | |
| gap: 8px; | |
| } | |
| .stTabs [data-baseweb="tab"] { | |
| height: 50px; | |
| white-space: pre-wrap; | |
| background-color: #f0f2f6; | |
| border-radius: 4px 4px 0px 0px; | |
| gap: 1px; | |
| padding-top: 10px; | |
| padding-bottom: 10px; | |
| } | |
| .stTabs [aria-selected="true"] { | |
| background-color: #4CAF50; | |
| color: white; | |
| } | |
| /* Button styling */ | |
| .stButton>button { | |
| border-radius: 20px; | |
| font-weight: 500; | |
| } | |
| /* Progress indicator */ | |
| .progress-container { | |
| display: flex; | |
| justify-content: space-between; | |
| margin-bottom: 30px; | |
| } | |
| .progress-step { | |
| text-align: center; | |
| flex: 1; | |
| } | |
| .progress-step-number { | |
| width: 30px; | |
| height: 30px; | |
| border-radius: 50%; | |
| background-color: #ddd; | |
| color: white; | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| margin: 0 auto 10px auto; | |
| } | |
| .progress-step.active .progress-step-number { | |
| background-color: #4CAF50; | |
| } | |
| .progress-step-title { | |
| font-size: 0.8rem; | |
| } | |
| </style> | |
| """, unsafe_allow_html=True) | |
| # User management functions | |
| def load_users(): | |
| try: | |
| with open("users.json", "r") as f: | |
| return json.load(f) | |
| except (FileNotFoundError, json.JSONDecodeError): | |
| return {} | |
| def save_users(users): | |
| with open("users.json", "w") as f: | |
| json.dump(users, f) | |
| def authenticate(username, password): | |
| users = load_users() | |
| if username in users and users[username]["password"] == password: | |
| return True | |
| return False | |
| def register_user(username, password, email): | |
| users = load_users() | |
| if username in users: | |
| return False | |
| users[username] = { | |
| "password": password, | |
| "email": email, | |
| "profile": {}, | |
| "saved_scholarships": [], | |
| "applications": {}, | |
| "created_at": datetime.datetime.now().isoformat() | |
| } | |
| save_users(users) | |
| return True | |
| # Saved scholarship functions | |
| def save_scholarship(username, scholarship_name, deadline): | |
| users = load_users() | |
| if username in users: | |
| # Check if already saved | |
| if scholarship_name not in [s["name"] for s in users[username]["saved_scholarships"]]: | |
| users[username]["saved_scholarships"].append({ | |
| "name": scholarship_name, | |
| "deadline": deadline, | |
| "saved_at": datetime.datetime.now().isoformat(), | |
| "status": "Saved" | |
| }) | |
| save_users(users) | |
| return True | |
| return False | |
| def get_saved_scholarships(username): | |
| users = load_users() | |
| if username in users: | |
| return users[username]["saved_scholarships"] | |
| return [] | |
| def update_scholarship_status(username, scholarship_name, status): | |
| users = load_users() | |
| if username in users: | |
| for scholarship in users[username]["saved_scholarships"]: | |
| if scholarship["name"] == scholarship_name: | |
| scholarship["status"] = status | |
| save_users(users) | |
| return True | |
| return False | |
| # Application tracking functions | |
| def track_application(username, scholarship_name, status="Started"): | |
| users = load_users() | |
| if username in users: | |
| if scholarship_name not in users[username]["applications"]: | |
| users[username]["applications"][scholarship_name] = { | |
| "status": status, | |
| "progress": 0, | |
| "started_at": datetime.datetime.now().isoformat(), | |
| "form_data": {} | |
| } | |
| save_users(users) | |
| return True | |
| return False | |
| def update_application(username, scholarship_name, form_data, progress): | |
| users = load_users() | |
| if username in users and scholarship_name in users[username]["applications"]: | |
| users[username]["applications"][scholarship_name]["form_data"] = form_data | |
| users[username]["applications"][scholarship_name]["progress"] = progress | |
| users[username]["applications"][scholarship_name]["updated_at"] = datetime.datetime.now().isoformat() | |
| save_users(users) | |
| return True | |
| return False | |
| def get_application_progress(username, scholarship_name): | |
| users = load_users() | |
| if username in users and scholarship_name in users[username]["applications"]: | |
| return users[username]["applications"][scholarship_name] | |
| return None | |
| # Email notification function | |
| def send_deadline_notification(email, scholarship_name, deadline_date): | |
| try: | |
| sender_email = os.getenv('APP_EMAIL', 'app_email@example.com') | |
| password = os.getenv('APP_EMAIL_PASSWORD', 'app_password') | |
| msg = MIMEMultipart() | |
| msg['From'] = sender_email | |
| msg['To'] = email | |
| msg['Subject'] = f"Deadline Reminder: {scholarship_name}" | |
| body = f""" | |
| <html> | |
| <body> | |
| <h2>Deadline Reminder</h2> | |
| <p>Hello,</p> | |
| <p>This is a reminder that the application deadline for <b>{scholarship_name}</b> is approaching.</p> | |
| <p>Deadline: <b>{deadline_date}</b></p> | |
| <p>Please log in to the AI Scholarship Advisor to complete your application.</p> | |
| <p>Best of luck!</p> | |
| </body> | |
| </html> | |
| """ | |
| msg.attach(MIMEText(body, 'html')) | |
| server = smtplib.SMTP('smtp.gmail.com', 587) | |
| server.starttls() | |
| server.login(sender_email, password) | |
| server.send_message(msg) | |
| server.quit() | |
| return True | |
| except Exception as e: | |
| st.error(f"Failed to send email: {str(e)}") | |
| return False | |
| # Profile management | |
| def update_user_profile(username, profile_data): | |
| users = load_users() | |
| if username in users: | |
| users[username]["profile"] = profile_data | |
| save_users(users) | |
| return True | |
| return False | |
| def get_user_profile(username): | |
| users = load_users() | |
| if username in users: | |
| return users[username]["profile"] | |
| return {} | |
| # Forum functions | |
| def load_forum_posts(): | |
| try: | |
| with open("forum_posts.json", "r") as f: | |
| return json.load(f) | |
| except (FileNotFoundError, json.JSONDecodeError): | |
| return [] | |
| def save_forum_posts(posts): | |
| with open("forum_posts.json", "w") as f: | |
| json.dump(posts, f) | |
| def add_forum_post(username, title, content, category): | |
| posts = load_forum_posts() | |
| post_id = str(uuid.uuid4()) | |
| posts.append({ | |
| "id": post_id, | |
| "username": username, | |
| "title": title, | |
| "content": content, | |
| "category": category, | |
| "created_at": datetime.datetime.now().isoformat(), | |
| "replies": [] | |
| }) | |
| save_forum_posts(posts) | |
| return post_id | |
| def add_forum_reply(post_id, username, content): | |
| posts = load_forum_posts() | |
| for post in posts: | |
| if post["id"] == post_id: | |
| reply_id = str(uuid.uuid4()) | |
| post["replies"].append({ | |
| "id": reply_id, | |
| "username": username, | |
| "content": content, | |
| "created_at": datetime.datetime.now().isoformat() | |
| }) | |
| save_forum_posts(posts) | |
| return reply_id | |
| return None | |
| # Create profile completion wizard | |
| def render_profile_wizard(username): | |
| st.markdown("### Complete Your Profile") | |
| # Progress indicator | |
| st.markdown(""" | |
| <div class="progress-container"> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">1</div> | |
| <div class="progress-step-title">Personal Info</div> | |
| </div> | |
| <div class="progress-step"> | |
| <div class="progress-step-number">2</div> | |
| <div class="progress-step-title">Academic Info</div> | |
| </div> | |
| <div class="progress-step"> | |
| <div class="progress-step-number">3</div> | |
| <div class="progress-step-title">Financial Info</div> | |
| </div> | |
| <div class="progress-step"> | |
| <div class="progress-step-number">4</div> | |
| <div class="progress-step-title">Preferences</div> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| profile = get_user_profile(username) | |
| step = st.session_state.get("profile_step", 1) | |
| if step == 1: | |
| with st.form("personal_info"): | |
| st.markdown("#### Step 1: Personal Information") | |
| first_name = st.text_input("First Name", profile.get("first_name", "")) | |
| last_name = st.text_input("Last Name", profile.get("last_name", "")) | |
| dob = st.date_input("Date of Birth", value=datetime.datetime.strptime(profile.get("dob", "2000-01-01"), "%Y-%m-%d").date() if "dob" in profile else datetime.date(2000, 1, 1)) | |
| gender = st.selectbox("Gender", ["Male", "Female", "Other", "Prefer not to say"], index=["Male", "Female", "Other", "Prefer not to say"].index(profile.get("gender", "Prefer not to say")) if "gender" in profile else 3) | |
| citizenship = st.selectbox("Citizenship", ["India", "Other"], index=["India", "Other"].index(profile.get("citizenship", "India")) if "citizenship" in profile else 0) | |
| if st.form_submit_button("Next"): | |
| profile.update({ | |
| "first_name": first_name, | |
| "last_name": last_name, | |
| "dob": dob.strftime("%Y-%m-%d"), | |
| "gender": gender, | |
| "citizenship": citizenship | |
| }) | |
| update_user_profile(username, profile) | |
| st.session_state.profile_step = 2 | |
| st.rerun() | |
| elif step == 2: | |
| st.markdown(""" | |
| <div class="progress-container"> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">1</div> | |
| <div class="progress-step-title">Personal Info</div> | |
| </div> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">2</div> | |
| <div class="progress-step-title">Academic Info</div> | |
| </div> | |
| <div class="progress-step"> | |
| <div class="progress-step-number">3</div> | |
| <div class="progress-step-title">Financial Info</div> | |
| </div> | |
| <div class="progress-step"> | |
| <div class="progress-step-number">4</div> | |
| <div class="progress-step-title">Preferences</div> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with st.form("academic_info"): | |
| st.markdown("#### Step 2: Academic Information") | |
| education = st.selectbox("Education Level", | |
| ["High School", "Undergraduate", "Postgraduate", "PhD"], | |
| index=["High School", "Undergraduate", "Postgraduate", "PhD"].index(profile.get("education", "Undergraduate")) if "education" in profile else 1) | |
| institution = st.text_input("Current Institution", profile.get("institution", "")) | |
| field_of_study = st.text_input("Field of Study", profile.get("field_of_study", "")) | |
| cgpa = st.number_input("CGPA (out of 10)", 0.0, 10.0, float(profile.get("cgpa", 8.0)) if "cgpa" in profile else 8.0, 0.1) | |
| achievements = st.text_area("Academic Achievements", profile.get("achievements", "")) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.form_submit_button("Previous"): | |
| st.session_state.profile_step = 1 | |
| st.rerun() | |
| with col2: | |
| if st.form_submit_button("Next"): | |
| profile.update({ | |
| "education": education, | |
| "institution": institution, | |
| "field_of_study": field_of_study, | |
| "cgpa": cgpa, | |
| "achievements": achievements | |
| }) | |
| update_user_profile(username, profile) | |
| st.session_state.profile_step = 3 | |
| st.rerun() | |
| elif step == 3: | |
| st.markdown(""" | |
| <div class="progress-container"> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">1</div> | |
| <div class="progress-step-title">Personal Info</div> | |
| </div> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">2</div> | |
| <div class="progress-step-title">Academic Info</div> | |
| </div> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">3</div> | |
| <div class="progress-step-title">Financial Info</div> | |
| </div> | |
| <div class="progress-step"> | |
| <div class="progress-step-number">4</div> | |
| <div class="progress-step-title">Preferences</div> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with st.form("financial_info"): | |
| st.markdown("#### Step 3: Financial Information") | |
| income = st.number_input("Annual Family Income (₹)", 0, 10000000, int(profile.get("income", 300000)) if "income" in profile else 300000, 10000) | |
| category = st.selectbox("Category", | |
| ["General", "OBC", "SC", "ST", "EWS", "Minority"], | |
| index=["General", "OBC", "SC", "ST", "EWS", "Minority"].index(profile.get("category", "General")) if "category" in profile else 0) | |
| financial_need = st.slider("Financial Need Level", 1, 10, int(profile.get("financial_need", 5)) if "financial_need" in profile else 5) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.form_submit_button("Previous"): | |
| st.session_state.profile_step = 2 | |
| st.rerun() | |
| with col2: | |
| if st.form_submit_button("Next"): | |
| profile.update({ | |
| "income": income, | |
| "category": category, | |
| "financial_need": financial_need | |
| }) | |
| update_user_profile(username, profile) | |
| st.session_state.profile_step = 4 | |
| st.rerun() | |
| elif step == 4: | |
| st.markdown(""" | |
| <div class="progress-container"> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">1</div> | |
| <div class="progress-step-title">Personal Info</div> | |
| </div> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">2</div> | |
| <div class="progress-step-title">Academic Info</div> | |
| </div> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">3</div> | |
| <div class="progress-step-title">Financial Info</div> | |
| </div> | |
| <div class="progress-step active"> | |
| <div class="progress-step-number">4</div> | |
| <div class="progress-step-title">Preferences</div> | |
| </div> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| with st.form("preferences"): | |
| st.markdown("#### Step 4: Preferences") | |
| preferred_locations = st.multiselect( | |
| "Preferred Study Locations", | |
| ["India", "USA", "UK", "Canada", "Australia", "Germany", "Japan", "Singapore", "Other"], | |
| profile.get("preferred_locations", ["India"]) | |
| ) | |
| study_interests = st.multiselect( | |
| "Fields of Interest", | |
| ["Engineering", "Medicine", "Law", "Business", "Arts", "Science", "Humanities", "Social Sciences", "Other"], | |
| profile.get("study_interests", ["Engineering"]) | |
| ) | |
| career_goals = st.text_area("Career Goals", profile.get("career_goals", "")) | |
| extracurricular = st.text_area("Extracurricular Activities", profile.get("extracurricular", "")) | |
| notification_preference = st.checkbox("Receive Email Notifications", value=profile.get("notification_preference", True)) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.form_submit_button("Previous"): | |
| st.session_state.profile_step = 3 | |
| st.rerun() | |
| with col2: | |
| if st.form_submit_button("Complete Profile"): | |
| profile.update({ | |
| "preferred_locations": preferred_locations, | |
| "study_interests": study_interests, | |
| "career_goals": career_goals, | |
| "extracurricular": extracurricular, | |
| "notification_preference": notification_preference, | |
| "profile_completed": True, | |
| "completed_at": datetime.datetime.now().isoformat() | |
| }) | |
| update_user_profile(username, profile) | |
| st.session_state.profile_complete = True | |
| st.success("Profile completed successfully!") | |
| st.rerun() | |
| # Auto-fill application form | |
| def render_application_form(username, scholarship_name, df): | |
| st.markdown(f"### Application Form: {scholarship_name}") | |
| # Get scholarship details | |
| scholarship_row = df[df['Scholarship Name'] == scholarship_name].iloc[0] | |
| deadline = scholarship_row['Deadline'] | |
| eligibility = scholarship_row['Eligibility'] | |
| link = scholarship_row['Link'] | |
| st.info(f"Deadline: {deadline}") | |
| st.markdown(f"Eligibility: {eligibility}") | |
| # Get user profile for auto-fill | |
| profile = get_user_profile(username) | |
| # Get existing application data if any | |
| app_data = get_application_progress(username, scholarship_name) | |
| form_data = app_data["form_data"] if app_data and "form_data" in app_data else {} | |
| with st.form("application_form"): | |
| st.markdown("#### Personal Information") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| first_name = st.text_input("First Name", value=form_data.get("first_name", profile.get("first_name", ""))) | |
| last_name = st.text_input("Last Name", value=form_data.get("last_name", profile.get("last_name", ""))) | |
| with col2: | |
| email = st.text_input("Email", value=form_data.get("email", profile.get("email", ""))) | |
| phone = st.text_input("Phone Number", value=form_data.get("phone", "")) | |
| st.markdown("#### Academic Information") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| institution = st.text_input("Institution", value=form_data.get("institution", profile.get("institution", ""))) | |
| education = st.selectbox("Education Level", | |
| ["High School", "Undergraduate", "Postgraduate", "PhD"], | |
| index=["High School", "Undergraduate", "Postgraduate", "PhD"].index(form_data.get("education", profile.get("education", "Undergraduate"))) if "education" in form_data or "education" in profile else 1) | |
| with col2: | |
| field_of_study = st.text_input("Field of Study", value=form_data.get("field_of_study", profile.get("field_of_study", ""))) | |
| cgpa = st.number_input("CGPA", 0.0, 10.0, float(form_data.get("cgpa", profile.get("cgpa", 8.0))) if "cgpa" in form_data or "cgpa" in profile else 8.0, 0.1) | |
| st.markdown("#### Essay Questions") | |
| why_deserve = st.text_area("Why do you deserve this scholarship? (200-300 words)", value=form_data.get("why_deserve", "")) | |
| career_goals = st.text_area("Describe your career goals (200-300 words)", value=form_data.get("career_goals", profile.get("career_goals", ""))) | |
| st.markdown("#### Additional Documents") | |
| st.file_uploader("Upload Resume/CV (PDF)", type=["pdf"]) | |
| st.file_uploader("Upload Transcripts (PDF)", type=["pdf"]) | |
| st.file_uploader("Upload Recommendation Letter (PDF)", type=["pdf"]) | |
| # Form actions | |
| col1, col2, col3 = st.columns(3) | |
| with col1: | |
| save_draft = st.form_submit_button("Save as Draft") | |
| with col2: | |
| submit_later = st.form_submit_button("Submit Later") | |
| with col3: | |
| submit_app = st.form_submit_button("Submit Application") | |
| # Handle form submission | |
| if save_draft or submit_later or submit_app: | |
| new_form_data = { | |
| "first_name": first_name, | |
| "last_name": last_name, | |
| "email": email, | |
| "phone": phone, | |
| "institution": institution, | |
| "education": education, | |
| "field_of_study": field_of_study, | |
| "cgpa": cgpa, | |
| "why_deserve": why_deserve, | |
| "career_goals": career_goals | |
| } | |
| progress = 25 # Initial progress | |
| # Calculate form completion progress | |
| if first_name and last_name and email and phone: | |
| progress += 25 | |
| if institution and field_of_study: | |
| progress += 25 | |
| if why_deserve and len(why_deserve) > 100: | |
| progress += 15 | |
| if career_goals and len(career_goals) > 100: | |
| progress += 10 | |
| # Update application status | |
| status = "Draft" | |
| if submit_app: | |
| status = "Submitted" | |
| progress = 100 | |
| elif submit_later: | |
| status = "In Progress" | |
| # Create or update application tracking | |
| if app_data: | |
| update_application(username, scholarship_name, new_form_data, progress) | |
| else: | |
| track_application(username, scholarship_name, status) | |
| update_application(username, scholarship_name, new_form_data, progress) | |
| # Update scholarship status in saved list | |
| update_scholarship_status(username, scholarship_name, status) | |
| if submit_app: | |
| st.success("Application submitted successfully!") | |
| elif save_draft: | |
| st.info("Draft saved successfully.") | |
| elif submit_later: | |
| st.info("Application saved. You can continue later.") | |
| # Only refresh if not exiting | |
| if not submit_app: | |
| st.rerun() | |
| # Forum feature | |
| def render_forum(username): | |
| st.markdown("### Scholarship Community Forum") | |
| tab1, tab2 = st.tabs(["Browse Discussions", "Create New Post"]) | |
| with tab1: | |
| posts = load_forum_posts() | |
| # Filter options | |
| categories = ["All Categories", "Application Tips", "Scholarship Advice", "University Selection", "Financial Aid", "Study Abroad", "Career Guidance"] | |
| filter_category = st.selectbox("Filter by Category", categories) | |
| # Sort options | |
| sort_option = st.selectbox("Sort by", ["Newest First", "Oldest First", "Most Replies"]) | |
| # Apply filters and sorting | |
| if filter_category != "All Categories": | |
| filtered_posts = [post for post in posts if post["category"] == filter_category] | |
| else: | |
| filtered_posts = posts | |
| if sort_option == "Newest First": | |
| filtered_posts.sort(key=lambda x: x["created_at"], reverse=True) | |
| elif sort_option == "Oldest First": | |
| filtered_posts.sort(key=lambda x: x["created_at"]) | |
| elif sort_option == "Most Replies": | |
| filtered_posts.sort(key=lambda x: len(x["replies"]), reverse=True) | |
| # Display posts | |
| if not filtered_posts: | |
| st.info("No discussions found. Be the first to start a conversation!") | |
| for post in filtered_posts: | |
| with st.expander(f"{post['title']} - by {post['username']} - {post['category']}"): | |
| st.markdown(f"**{post['title']}**") | |
| st.markdown(post['content']) | |
| st.markdown(f"*Posted on: {datetime.datetime.fromisoformat(post['created_at']).strftime('%Y-%m-%d %H:%M')}*") | |
| st.divider() | |
| # Display replies | |
| if post["replies"]: | |
| st.markdown("#### Replies") | |
| for reply in post["replies"]: | |
| st.markdown(f"**{reply['username']}**: {reply['content']}") | |
| st.markdown(f"*{datetime.datetime.fromisoformat(reply['created_at']).strftime('%Y-%m-%d %H:%M')}*") | |
| st.divider() | |
| # Reply form | |
| with st.form(f"reply_form_{post['id']}"): | |
| reply_content = st.text_area("Reply to this post", key=f"reply_{post['id']}") | |
| if st.form_submit_button("Post Reply"): | |
| if reply_content: | |
| add_forum_reply(post["id"], username, reply_content) | |
| st.success("Reply posted successfully!") | |
| st.rerun() | |
| with tab2: | |
| with st.form("new_post_form"): | |
| st.markdown("#### Create New Discussion") | |
| post_title = st.text_input("Title") | |
| post_category = st.selectbox("Category", categories[1:]) # Exclude "All Categories" | |
| post_content = st.text_area("Content", height=200) | |
| if st.form_submit_button("Post Discussion"): | |
| if post_title and post_content: | |
| add_forum_post(username, post_title, post_content, post_category) | |
| st.success("Discussion posted successfully!") | |
| st.rerun() | |
| else: | |
| st.error("Please fill in all required fields.") | |
| # Mentorship and skill development (future scope preview) | |
| def render_mentorship_preview(): | |
| st.markdown("### 🚀 Coming Soon: Mentorship & Skill Development") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown(""" | |
| #### 👨🏫 Mentorship Program | |
| - Connect with experienced mentors in your field | |
| - Get personalized guidance for scholarship applications | |
| - Weekly 1:1 mentorship sessions | |
| - Career planning and academic advice | |
| """) | |
| with col2: | |
| st.markdown(""" | |
| #### 🧠 Skill Development | |
| - Free courses tailored to scholarship requirements | |
| - Interview preparation workshops | |
| - Essay writing masterclasses | |
| - Language proficiency training | |
| """) | |
| st.info("These features are coming soon! Join our waitlist to be notified when they launch.") | |
| with st.form("waitlist_form"): | |
| waitlist_email = st.text_input("Email address") | |
| interests = st.multiselect("I'm interested in", ["Mentorship", "Skill Development", "Both"]) | |
| if st.form_submit_button("Join Waitlist"): | |
| if waitlist_email: | |
| st.success("Thank you for joining our waitlist! We'll notify you when these features launch.") | |
| else: | |
| st.error("Please enter your email address.") | |
| # Financial planning feature (future scope preview) | |
| def render_financial_planning_preview(): | |
| st.markdown("### 💰 Financial Planning Tools") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown(""" | |
| #### 📊 Scholarship Budget Planner | |
| - Calculate total education expenses | |
| - Track scholarship applications and potential funding | |
| - Gap analysis between costs and available funding | |
| - Prioritize applications based on financial need | |
| """) | |
| with col2: | |
| st.markdown(""" | |
| #### 💸 Financial Literacy Resources | |
| - Educational content on managing scholarship funds | |
| - Tax implications of scholarships | |
| - Combining scholarships with student loans | |
| - Building credit history as a student | |
| """) | |
| st.info("These financial planning tools are coming soon! Join our waitlist to be notified when they launch.") | |
| # Sample financial planning calculator preview | |
| st.markdown("#### 🔍 Education Cost Calculator Preview") | |
| with st.form("cost_calculator"): | |
| tuition = st.number_input("Estimated Annual Tuition (₹)", 0, 2000000, 100000, 10000) | |
| living = st.number_input("Annual Living Expenses (₹)", 0, 1000000, 120000, 10000) | |
| books = st.number_input("Books and Supplies (₹)", 0, 100000, 15000, 1000) | |
| travel = st.number_input("Travel Expenses (₹)", 0, 100000, 20000, 1000) | |
| years = st.number_input("Program Duration (years)", 1, 6, 4, 1) | |
| if st.form_submit_button("Calculate Total Cost"): | |
| annual_cost = tuition + living + books + travel | |
| total_cost = annual_cost * years | |
| st.markdown(f"**Annual Cost:** ₹{annual_cost:,}") | |
| st.markdown(f"**Total Program Cost:** ₹{total_cost:,}") | |
| # Display funding gap visualization | |
| st.markdown("#### Funding Gap Analysis") | |
| st.progress(0.2) | |
| st.markdown("20% of costs currently covered by identified scholarships") | |
| # Career alignment feature (future scope preview) | |
| def render_career_alignment_preview(): | |
| st.markdown("### 🎯 Career Alignment Tools") | |
| st.markdown(""" | |
| Our upcoming Career Alignment feature will help you connect your scholarship journey with your long-term career goals. | |
| """) | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| st.markdown(""" | |
| #### 🧭 Career Pathway Mapping | |
| - Personalized career roadmap based on your profile | |
| - Identify skills gaps and development opportunities | |
| - Connect with industry professionals | |
| - Internship and job placement assistance | |
| """) | |
| with col2: | |
| st.markdown(""" | |
| #### 🏆 Post-Scholarship Success | |
| - Resume and portfolio building workshops | |
| - Interview preparation specifically for scholars | |
| - Alumni network access | |
| - Scholarship to job transition guidance | |
| """) | |
| # AI Career Recommendation Preview | |
| st.markdown("#### 🤖 AI Career Recommendation (Preview)") | |
| with st.form("career_recommendation"): | |
| interests = st.multiselect( | |
| "Select your interests", | |
| ["Technology", "Healthcare", "Business", "Arts", "Sciences", "Education", "Law", "Engineering"] | |
| ) | |
| skills = st.multiselect( | |
| "Select your top skills", | |
| ["Programming", "Data Analysis", "Writing", "Research", "Design", "Leadership", "Problem-Solving", "Communication"] | |
| ) | |
| values = st.multiselect( | |
| "What do you value in a career?", | |
| ["Work-Life Balance", "High Income", "Making an Impact", "Creativity", "Recognition", "Stability", "Independence", "Growth"] | |
| ) | |
| if st.form_submit_button("Get AI Career Recommendations"): | |
| if interests and skills and values: | |
| st.info("Based on your profile, we recommend exploring these career paths:") | |
| if "Technology" in interests and "Programming" in skills: | |
| st.markdown("1. **Software Development Engineer** - Aligned with your technical interests and problem-solving skills") | |
| elif "Healthcare" in interests: | |
| st.markdown("1. **Healthcare Researcher** - Combines your interest in healthcare with analytical skills") | |
| elif "Business" in interests: | |
| st.markdown("1. **Business Analyst** - Leverages your data analysis skills in a business context") | |
| else: | |
| st.markdown("1. **Research Specialist** - Aligns with your analytical mindset and subject interests") | |
| st.markdown("*Full career alignment features coming soon!*") | |
| else: | |
| st.error("Please fill in all fields to get personalized recommendations.") | |
| # Streamlit app | |
| def main(): | |
| # Load custom CSS | |
| load_css() | |
| # Initialize session state | |
| if "authenticated" not in st.session_state: | |
| st.session_state.authenticated = False | |
| if "username" not in st.session_state: | |
| st.session_state.username = None | |
| if "profile_complete" not in st.session_state: | |
| st.session_state.profile_complete = False | |
| # Hero Section | |
| st.markdown(""" | |
| <div style="text-align: center; padding: 50px 0;"> | |
| <h1 style="color: #2c3e50; font-size: 3rem;">🎓 AI Scholarship Advisor</h1> | |
| <p style="color: #34495e; font-size: 1.2rem;">Find the best scholarships tailored just for you!</p> | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # User Authentication | |
| if not st.session_state.authenticated: | |
| tab1, tab2 = st.tabs(["Login", "Register"]) | |
| with tab1: | |
| with st.form("login_form"): | |
| username = st.text_input("Username") | |
| password = st.text_input("Password", type="password") | |
| if st.form_submit_button("Login"): | |
| if authenticate(username, password): | |
| st.session_state.authenticated = True | |
| st.session_state.username = username | |
| # Check if profile is complete | |
| profile = get_user_profile(username) | |
| if profile and profile.get("profile_completed", False): | |
| st.session_state.profile_complete = True | |
| st.rerun() | |
| else: | |
| st.error("Invalid username or password") | |
| with tab2: | |
| with st.form("register_form"): | |
| new_username = st.text_input("Username", key="reg_username") | |
| new_password = st.text_input("Password", type="password", key="reg_password") | |
| confirm_password = st.text_input("Confirm Password", type="password") | |
| email = st.text_input("Email Address") | |
| if st.form_submit_button("Register"): | |
| if new_password != confirm_password: | |
| st.error("Passwords do not match") | |
| elif not new_username or not new_password or not email: | |
| st.error("All fields are required") | |
| else: | |
| if register_user(new_username, new_password, email): | |
| st.success("Registration successful! Please login.") | |
| else: | |
| st.error("Username already exists") | |
| else: | |
| # User is authenticated | |
| username = st.session_state.username | |
| # Check profile completion | |
| profile = get_user_profile(username) | |
| profile_complete = profile.get("profile_completed", False) | |
| if not profile_complete and not st.session_state.profile_complete: | |
| # User profile needs to be completed | |
| render_profile_wizard(username) | |
| else: | |
| # Main application tabs | |
| tab1, tab2, tab3, tab4, tab5, tab6 = st.tabs([ | |
| "💡 Recommendations", | |
| "📋 Saved Scholarships", | |
| "📝 Applications", | |
| "💬 Community Forum", | |
| "🧠 Skill Development", | |
| "💰 Financial Planning" | |
| ]) | |
| # Load data | |
| df = load_scholarships() | |
| with tab1: | |
| st.markdown("### 🎯 Get Personalized Recommendations") | |
| # Get user profile for recommendations | |
| profile = get_user_profile(username) | |
| # User can modify certain profile elements for this search | |
| with st.form("profile_form"): | |
| st.markdown("### 📝 Customize Search Criteria") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| age = st.number_input("Age", 16, 50, int(profile.get("age", 20)) if "age" in profile else 20) | |
| citizenship = st.selectbox( | |
| "Citizenship", | |
| ["India", "Other"], | |
| index=0 if profile.get("citizenship", "India") == "India" else 1 | |
| ) | |
| income = st.number_input( | |
| "Annual Family Income (₹)", | |
| 0, 10000000, | |
| int(profile.get("income", 300000)) if "income" in profile else 300000 | |
| ) | |
| with col2: | |
| education = st.selectbox( | |
| "Education Level", | |
| ["High School", "Undergraduate", "Postgraduate", "PhD"], | |
| index=["High School", "Undergraduate", "Postgraduate", "PhD"].index(profile.get("education", "Undergraduate")) if "education" in profile else 1 | |
| ) | |
| category = st.selectbox( | |
| "Category", | |
| ["General", "OBC", "SC", "ST", "EWS", "Minority"], | |
| index=["General", "OBC", "SC", "ST", "EWS", "Minority"].index(profile.get("category", "General")) if "category" in profile else 0 | |
| ) | |
| submitted = st.form_submit_button("🚀 Get Recommendations") | |
| if submitted: | |
| # Create user profile | |
| user_profile = f""" | |
| Student Profile: | |
| - Age: {age} | |
| - Citizenship: {citizenship} | |
| - Annual Income: ₹{income} | |
| - Education Level: {education} | |
| - Category: {category} | |
| """ | |
| # Create RAG context | |
| rag_context = create_rag_context(df) | |
| # Generate response using RAG | |
| model = get_rag_model() | |
| prompt = f""" | |
| {rag_context} | |
| {user_profile} | |
| Task: | |
| 1. Analyze the student profile against all scholarships | |
| 2. Identify top 5 most relevant scholarships with priority order | |
| 3. For each scholarship: | |
| - List matching eligibility criteria | |
| - Explain why it's a good match | |
| - Provide direct application link | |
| 4. Format response with markdown headers and bullet points | |
| Important: | |
| - Be specific about eligibility matches | |
| - Highlight deadlines if available | |
| - Never invent scholarships not in the database | |
| """ | |
| with st.spinner("🔍 Analyzing 50+ scholarships..."): | |
| response = model.generate_content( | |
| prompt, | |
| generation_config=GenerationConfig( | |
| temperature=0.3, | |
| top_p=0.95, | |
| max_output_tokens=2000 | |
| ) | |
| ) | |
| # Display recommendations | |
| st.markdown("### 🎉 Personalized Recommendations") | |
| # Process the response to add save buttons | |
| recommendations_text = response.text | |
| # Split the recommendations into sections | |
| scholarship_sections = recommendations_text.split("##")[1:] # Skip the first split which is empty | |
| for section in scholarship_sections: | |
| if not section.strip(): | |
| continue | |
| # Extract scholarship name from the header | |
| lines = section.strip().split("\n") | |
| scholarship_name = lines[0].strip() | |
| # Find deadline if mentioned | |
| deadline = "Not specified" | |
| for line in lines: | |
| if "deadline" in line.lower(): | |
| deadline = line.split(":", 1)[1].strip() if ":" in line else line | |
| break | |
| # Create a card for this scholarship | |
| st.markdown(f""" | |
| <div class="scholarship-card"> | |
| <h3>{scholarship_name}</h3> | |
| {"".join([f"<p>{line}</p>" for line in lines[1:]])} | |
| </div> | |
| """, unsafe_allow_html=True) | |
| # Add a button to save this scholarship | |
| if st.button(f"Save this scholarship", key=f"save_{scholarship_name}"): | |
| if save_scholarship(username, scholarship_name, deadline): | |
| st.success(f"Saved {scholarship_name} to your list!") | |
| else: | |
| st.info("This scholarship is already in your saved list.") | |
| # Show raw data for transparency | |
| with st.expander("📊 View Full Scholarship Database"): | |
| st.dataframe(df) | |
| with tab2: | |
| st.markdown("### 📋 Your Saved Scholarships") | |
| saved = get_saved_scholarships(username) | |
| if not saved: | |
| st.info("You haven't saved any scholarships yet. Go to the Recommendations tab to find and save scholarships.") | |
| else: | |
| # Group by status | |
| saved_by_status = {} | |
| for s in saved: | |
| status = s.get("status", "Saved") | |
| if status not in saved_by_status: | |
| saved_by_status[status] = [] | |
| saved_by_status[status].append(s) | |
| # Create tabs for different statuses | |
| status_tabs = st.tabs(list(saved_by_status.keys())) | |
| for i, (status, scholarships) in enumerate(saved_by_status.items()): | |
| with status_tabs[i]: | |
| for scholarship in scholarships: | |
| with st.expander(f"{scholarship['name']} (Deadline: {scholarship['deadline']})"): | |
| st.markdown(f"**{scholarship['name']}**") | |
| st.markdown(f"Deadline: {scholarship['deadline']}") | |
| st.markdown(f"Saved on: {datetime.datetime.fromisoformat(scholarship['saved_at']).strftime('%Y-%m-%d')}") | |
| # Find full details in the dataframe | |
| scholarship_details = df[df['Scholarship Name'] == scholarship['name']] | |
| if not scholarship_details.empty: | |
| st.markdown(f"Eligibility: {scholarship_details.iloc[0]['Eligibility']}") | |
| st.markdown(f"Link: {scholarship_details.iloc[0]['Link']}") | |
| col1, col2 = st.columns(2) | |
| with col1: | |
| if st.button("Start Application", key=f"apply_{scholarship['name']}"): | |
| track_application(username, scholarship['name']) | |
| update_scholarship_status(username, scholarship['name'], "Started") | |
| st.session_state.current_application = scholarship['name'] | |
| st.rerun() | |
| with col2: | |
| if st.button("Set Reminder", key=f"remind_{scholarship['name']}"): | |
| # Get user email | |
| users = load_users() | |
| email = users[username]["email"] | |
| # Send notification | |
| if send_deadline_notification(email, scholarship['name'], scholarship['deadline']): | |
| st.success("Reminder email sent!") | |
| else: | |
| st.error("Failed to send reminder email.") | |
| with tab3: | |
| st.markdown("### 📝 Your Applications") | |
| # Check if a specific application is being viewed | |
| if "current_application" in st.session_state: | |
| render_application_form(username, st.session_state.current_application, df) | |
| if st.button("Back to All Applications"): | |
| del st.session_state.current_application | |
| st.rerun() | |
| else: | |
| # Get user's applications | |
| users = load_users() | |
| applications = users[username]["applications"] if username in users else {} | |
| if not applications: | |
| st.info("You haven't started any applications yet. Save a scholarship and click 'Start Application' to begin.") | |
| else: | |
| # Group by status/progress | |
| in_progress = [] | |
| completed = [] | |
| drafts = [] | |
| for name, app in applications.items(): | |
| if app["progress"] == 100: | |
| completed.append((name, app)) | |
| elif app["status"] == "Draft": | |
| drafts.append((name, app)) | |
| else: | |
| in_progress.append((name, app)) | |
| # Create tabs for different statuses | |
| app_tabs = st.tabs(["In Progress", "Drafts", "Completed"]) | |
| with app_tabs[0]: | |
| if not in_progress: | |
| st.info("No applications in progress.") | |
| else: | |
| for name, app in in_progress: | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| st.markdown(f"**{name}**") | |
| st.progress(app["progress"] / 100) | |
| st.markdown(f"Progress: {app['progress']}% complete") | |
| with col2: | |
| if st.button("Continue", key=f"continue_{name}"): | |
| st.session_state.current_application = name | |
| st.rerun() | |
| with app_tabs[1]: | |
| if not drafts: | |
| st.info("No draft applications.") | |
| else: | |
| for name, app in drafts: | |
| col1, col2 = st.columns([3, 1]) | |
| with col1: | |
| st.markdown(f"**{name}**") | |
| st.markdown(f"Last updated: {datetime.datetime.fromisoformat(app.get('updated_at', app['started_at'])).strftime('%Y-%m-%d')}") | |
| with col2: | |
| if st.button("Edit Draft", key=f"edit_{name}"): | |
| st.session_state.current_application = name | |
| st.rerun() | |
| with app_tabs[2]: | |
| if not completed: | |
| st.info("No completed applications.") | |
| else: | |
| for name, app in completed: | |
| st.markdown(f"**{name}**") | |
| st.markdown(f"Submitted on: {datetime.datetime.fromisoformat(app.get('updated_at', app['started_at'])).strftime('%Y-%m-%d')}") | |
| st.success("Application completed and submitted!") | |
| with tab4: | |
| render_forum(username) | |
| with tab5: | |
| render_mentorship_preview() | |
| with tab6: | |
| st.markdown("### Financial Planning Tools") | |
| tab1, tab2 = st.tabs(["Education Financing", "Career Planning"]) | |
| with tab1: | |
| render_financial_planning_preview() | |
| with tab2: | |
| render_career_alignment_preview() | |
| # Logout button | |
| if st.sidebar.button("Logout"): | |
| st.session_state.authenticated = False | |
| st.session_state.username = None | |
| st.session_state.profile_complete = False | |
| if "current_application" in st.session_state: | |
| del st.session_state.current_application | |
| if "profile_step" in st.session_state: | |
| del st.session_state.profile_step | |
| st.rerun() | |
| if __name__ == "__main__": | |
| main() |