import gradio as gr import json import pandas as pd import os DATA_FILE = os.path.join("data", "teamup_data.json") ADMIN_CODE = os.getenv("ADMIN_CODE", "") # Ensure data file exists os.makedirs("data", exist_ok=True) if not os.path.exists(DATA_FILE) or os.path.getsize(DATA_FILE) == 0: with open(DATA_FILE, "w") as f: json.dump([], f) def submit_profile(name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea): print("🟢 Submit button clicked.") print(f"Incoming: {discord=}, {city=}, {country=}, {languages=}, {laptop=}, {robot=}") if not discord or not city or not country or not laptop or not robot: return "❌ Please fill in all required fields." if not languages or not isinstance(languages, list) or len(languages) == 0: return "❌ Please select at least one language." # Ensure country is stored as a string (in case form allows lists) if isinstance(country, list): country = country[0] if country else "" with open(DATA_FILE, "r") as f: data = json.load(f) for d in data: if d["Discord"].lower() == discord.lower(): d.update({ "Name": name, "City": city, "Country": country, "Address": address, "Looking for Team": looking, "Onlinecheck": onlinecheck, "Languages": languages, "Laptop": laptop, "Robot": robot, "Skills": skills, "Describe3": describe3, "Experience": experience, "Project Idea": idea }) break else: data.append({ "Name": name, "Discord": discord, "City": city, "Country": country, "Address": address, "Looking for Team": looking, "Onlinecheck": onlinecheck, "Languages": languages, "Laptop": laptop, "Robot": robot, "Skills": skills, "Describe3": describe3, "Experience": experience, "Project Idea": idea }) try: with open(DATA_FILE, "w") as f: json.dump(data, f, indent=2) print(f"✅ Successfully wrote {len(data)} profiles to {DATA_FILE}") except Exception as e: print(f"❌ Failed to write to {DATA_FILE}: {e}") return "❌ Error saving your profile. Please try again." return "✅ Profile saved!" def filter_by_fields(selected_country, selected_city, selected_language): with open(DATA_FILE, "r") as f: data = json.load(f) df = pd.DataFrame(data) # Convert list values to readable strings df["Languages"] = df["Languages"].apply(lambda langs: ", ".join(langs) if isinstance(langs, list) else langs) if df.empty or "Country" not in df.columns or "Languages" not in df.columns: return "

No participants found.

" if selected_country != "All": df = df[df["Country"] == selected_country] if selected_city != "All": df = df[df["City"] == selected_city] if selected_language != "All": df = df[df["Languages"].apply(lambda langs: selected_language in langs)] # Hide address if "Address" in df.columns: df = df.drop(columns=["Address"]) # Rename column headers for display only display_names = { "Discord": "Discord", "Name": "Name", "City": "City", "Country": "Country", "Looking for Team": "Looking for Team", "Onlinecheck": "How?", "Languages": "Languages", "Laptop": "Laptop", "Robot": "Robot", "Skills": "Skills", "Describe3": "Describe", "Experience": "Experience", "Project Idea": "Project Idea" } html = '

🔍 Find your matching Teammates & Register your team here👈👈

' html += "" # Header row html += "" + "".join( f"" for col in df.columns ) + "" # Data rows for _, row in df.iterrows(): html += "" for col in df.columns: val = row[col] if col == "Discord": val = f"{val}" html += f"" html += "" html += "
{display_names.get(col, col)}
{val}
" return html def update_dropdowns(): with open(DATA_FILE, "r") as f: data = json.load(f) if not data: return ["All"], ["All"], ["All"] df = pd.DataFrame(data) if "Country" not in df.columns or "Languages" not in df.columns or "City" not in df.columns: return ["All"], ["All"], ["All"] country_choices = sorted(list(df["Country"].dropna().unique())) city_choices = sorted(list(df["City"].dropna().unique())) language_set = set() for lang_list in df["Languages"].dropna(): language_set.update(lang_list) return ( ["All"] + country_choices, ["All"] + sorted(language_set), ["All"] + city_choices ) def delete_by_discord(discord, code): if code != ADMIN_CODE: return "❌ Invalid admin code." with open(DATA_FILE, "r") as f: data = json.load(f) new_data = [d for d in data if d["Discord"].lower() != discord.lower()] with open(DATA_FILE, "w") as f: json.dump(new_data, f, indent=2) return f"🗑️ Deleted user with Discord: {discord}" with gr.Blocks() as demo: gr.Markdown("# 🌍 LeRobot Worldwide Hackathon - Team-Up Dashboard") gr.Markdown("1. Submit or update your profile to find matching teammates and contact them on Discord. (Required fields marked with *.) ") with gr.Row(): with gr.Column(): name = gr.Text(label="Name") discord = gr.Text(label="👤 Discord Username *") city = gr.Text(label="📍 City *") country = gr.Text(label="🌍 Country *") address = gr.Text(label="Address (optional)") looking = gr.Radio(["Yes", "No"], label="🔍 Looking for a team?") onlinecheck = gr.Radio(["Participate Online", "Join a Local Hackathon"], label="🚀 I will...") languages = gr.CheckboxGroup(choices=["English", "French", "Spanish", "German", "Portuguese", "Chinese", "Arabic", "Hindi"], label="Languages Spoken *") laptop = gr.Text(label="💻 Laptop Setup *") robot = gr.Text(label="Robot Setup *") skills = gr.Text(label="🧠 Your Skills (comma separated)") describe3 = gr.Text(label="🤗 3 Words That Describe You") experience = gr.Dropdown(choices=["Beginner", "Intermediate", "Advanced"], label="Experience Level", value="Beginner") idea = gr.Textbox(label="Project Idea (optional)") submit_btn = gr.Button("Submit or Update Profile ✅") status = gr.Textbox(label="", interactive=False) with gr.Column(): gr.Markdown("🎯 2. Choose your preferences to find your teammates (country, city or language)") country_filter = gr.Dropdown(label="Filter by Country", choices=["All"], value="All", allow_custom_value=False) city_filter = gr.Dropdown(label="Filter by City", choices=["All"], value="All", allow_custom_value=False) language_filter = gr.Dropdown(label="Filter by Language", choices=["All"], value="All", allow_custom_value=False) table_html = gr.HTML(label="Matching Participants") submit_btn.click( submit_profile, inputs=[name, discord, city, country, address, looking, onlinecheck, languages, laptop, robot, skills, describe3, experience, idea], outputs=[status] ) def update_dropdown_choices(): with open(DATA_FILE, "r") as f: data = json.load(f) df = pd.DataFrame(data) country_choices = sorted(df["Country"].dropna().unique()) if "Country" in df else [] city_choices = sorted(df["City"].dropna().unique()) if "City" in df else [] language_set = set() if "Languages" in df: for lang_list in df["Languages"].dropna(): if isinstance(lang_list, list): language_set.update(lang_list) elif isinstance(lang_list, str): language_set.update(lang_list.split(", ")) return ( gr.update(choices=["All"] + list(country_choices), value="All"), gr.update(choices=["All"] + list(city_choices), value="All"), gr.update(choices=["All"] + sorted(language_set), value="All") ) def download_csv(code): if code != ADMIN_CODE: raise gr.Error("❌ Invalid admin code.") with open(DATA_FILE, "r") as f: data = json.load(f) df = pd.DataFrame(data) csv_path = os.path.join("data", "teamup_export.csv") df.to_csv(csv_path, index=False) return csv_path with demo: demo.load( fn=lambda: filter_by_fields("All", "All", "All"), inputs=[], outputs=[table_html] ) demo.load(fn=update_dropdown_choices, outputs=[country_filter, city_filter, language_filter]) country_filter.change(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=table_html) city_filter.change(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=table_html) language_filter.change(fn=filter_by_fields, inputs=[country_filter, city_filter, language_filter], outputs=table_html) gr.Markdown("---\n### 🛡️ Admin Panel (delete by Discord)") admin_discord = gr.Text(label="Discord Username") admin_code = gr.Text(label="Admin Code", type="password") del_btn = gr.Button("Delete Profile") del_status = gr.Textbox(label="Status", interactive=False) del_btn.click(delete_by_discord, inputs=[admin_discord, admin_code], outputs=del_status) # 🔐 CSV Download Section (admin-only) gr.Markdown("---\n### 📥 Admin Export CSV") export_code = gr.Text(label="Admin Code", type="password") download_btn = gr.Button("Generate and Download CSV") download_file = gr.File(label="CSV Export", interactive=False) download_btn.click(fn=download_csv, inputs=[export_code], outputs=[download_file]) demo.launch()