import dash from dash import dcc, html, Input, Output, State, dash_table import pandas as pd import os import datetime import base64 import io from google_sheet import fetch_leaderboard from google_drive import upload_to_drive # Make sure submissions folder exists os.makedirs("submissions", exist_ok=True) app = dash.Dash(__name__) app.title = "🏆 Hackathon Leaderboard" app.layout = html.Div([ html.H2("🏆 Hackathon Leaderboard"), dcc.Upload( id='upload-data', children=html.Div([ '📁 Drag and drop or click to upload a .zip file' ]), style={ 'width': '50%', 'height': '60px', 'lineHeight': '60px', 'borderWidth': '1px', 'borderStyle': 'dashed', 'borderRadius': '10px', 'textAlign': 'center', 'margin': '20px' }, multiple=False, accept='.zip' ), html.Button('Submit', id='submit-btn', n_clicks=0), html.Div(id='upload-status', style={'margin': '20px', 'fontWeight': 'bold'}), html.H3("Leaderboard"), html.Div(id='leaderboard-table', style={'margin': '20px'}) ]) def save_file_and_upload(content, filename): timestamp = datetime.datetime.now().isoformat().replace(':', '_') saved_filename = f"{timestamp}_{filename}" path = os.path.join("submissions", saved_filename) # Decode and save the file content_string = content.split(',')[1] decoded = base64.b64decode(content_string) with open(path, 'wb') as f: f.write(decoded) # Upload to Google Drive try: drive_file_id = upload_to_drive(path, saved_filename) return f"✅ Uploaded to Google Drive [File ID: {drive_file_id}]" except Exception as e: return f"⚠️ Failed to upload to Google Drive: {e}" def generate_leaderboard(): try: df = fetch_leaderboard() if df.empty: return html.Div("No submissions yet.") df_sorted = df.sort_values(by="score", ascending=False) return dash_table.DataTable( data=df_sorted.to_dict("records"), columns=[{"name": i, "id": i} for i in df_sorted.columns], style_table={'overflowX': 'auto'}, style_cell={'textAlign': 'left', 'padding': '5px'}, style_header={'backgroundColor': 'lightgrey', 'fontWeight': 'bold'} ) except Exception as e: return html.Div(f"Could not load leaderboard: {e}") @app.callback( Output('upload-status', 'children'), Output('leaderboard-table', 'children'), Input('submit-btn', 'n_clicks'), State('upload-data', 'contents'), State('upload-data', 'filename'), prevent_initial_call=True ) def handle_submission(n_clicks, contents, filename): if contents is None: return "❌ No file uploaded.", generate_leaderboard() status = save_file_and_upload(contents, filename) leaderboard = generate_leaderboard() return status, leaderboard if __name__ == '__main__': app.run(debug=True)