from nicegui import ui, app from data import database, data_api from gui import discord_login, gui_style def setup_routes(): @ui.page('/') def home_page(): gui_style.apply_design() # --------------------------- # --- NAVIGATIONSLEISTE (HEADER) --- # --------------------------- with ui.header().classes('items-center justify-between bg-zinc-900 p-4 shadow-lg'): # --- LINKE SEITE --- # Vereinslogo und den Titel in einer eigenen Reihe (Reihe 1) with ui.row().classes('items-center gap-4'): ui.image("gui/pictures/wsdg.png").classes('w-20 h-20 rounded-full') ui.label('Diceghost Liga').classes('text-2xl font-bold text-white') # --- RECHTE SEITE --- if app.storage.user.get('authenticated', False): with ui.row().classes('items-center gap-4'): discord_name = app.storage.user.get('discord_name') display_name = app.storage.user.get('display_name') player_id = app.storage.user.get('db_id') # 1. kleine Funktion, die zwischen Text und Eingabe hin- und herschaltet def toggle_edit_mode(): display_row.visible = not display_row.visible edit_row.visible = not edit_row.visible # --- ANSICHT 1: Der normale Text mit Edit-Button --- with ui.row().classes('items-center gap-2') as display_row: ui.label(display_name).classes('text-xl font-bold text-white') ui.label('aka').classes('text-sm text-gray-500') ui.label(discord_name).classes('text-lg text-gray-400') # Ein runder Button (.props('round')) ui.button(icon='edit', color='primary', on_click=toggle_edit_mode).props('round dense') # --- ANSICHT 2: Das Eingabefeld (startet unsichtbar!) --- with ui.row().classes('items-center gap-2') as edit_row: edit_row.visible = False # Am Anfang verstecken def save_new_name(): new_name = name_input.value # Nur speichern, wenn ein Name drinsteht und er anders ist als vorher if new_name and new_name != display_name: print("save") data_api.change_display_name(player_id, new_name) # Deine DB Funktion app.storage.user['display_name'] = new_name ui.notify('Name gespeichert!', color='positive') ui.navigate.reload() else: # Wenn nichts geändert wurde, einfach wieder einklappen toggle_edit_mode() name_input = ui.input('Neuer Name', value=display_name).on('keydown.enter', save_new_name) ui.button(icon='save', color='positive', on_click=save_new_name).props('round dense') ui.button(icon='close', color='negative', on_click=toggle_edit_mode).props('round dense') avatar = app.storage.user.get('avatar_url') if avatar: ui.image(avatar).classes('w-12 h-12 rounded-full border-2 border-red-500') def logout(): app.storage.user.clear() ui.navigate.to('/') ui.button('Logout', on_click=logout).classes('bg-red-500 text-white') else: auth_url = discord_login.get_auth_url() ui.button('Login with Discord', on_click=lambda: ui.navigate.to(auth_url)) # --------------------------- # --- Spielsysteme --- # --------------------------- if app.storage.user.get('authenticated', False): with ui.card().classes("w-full"): ui.label(text="Meine Ligaplätze").classes("font-bold text-white text-xl") placements = data_api.get_player_statistics(player_id) systems = data_api.get_gamesystem_data() def click_join_league(p_id, sys_id): data_api.join_league(p_id, sys_id) ui.navigate.to("/") # --- NEU: Wir machen die Funktion allgemein --- def toggle_visibility(row_a, row_b): row_a.visible = not row_a.visible row_b.visible = not row_b.visible with ui.element('div').classes("w-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 items-center"): for place in placements: sys_card = ui.card().classes("h-60 w-full items-center justify-center transition-colors") with sys_card: # Kopfzeile der Karte (Name & Beschreibung) ui.label(text=place['gamesystem_name']).classes('text-xl font-bold') if 'description' in place and place['description']: ui.label(text=place['description']).classes('text-xs text-gray-400') ui.space() if place['mmr'] is None: ui.label(text="Du bist noch nicht in dieser Liga.").classes("text-red-500 font-bold") # 1. Wir legen die Reihen an und speichern sie in lokalen Variablen join_row = ui.row().classes('items-center gap-2') confirm_row = ui.row().classes('items-center gap-2') confirm_row.visible = False # Standardmäßig unsichtbar # 2. Erste Reihe (Der "Beitreten" Button) with join_row: ui.button("Beitreten", on_click=lambda e, r1=join_row, r2=confirm_row: toggle_visibility(r1, r2)) # 3. Zweite Reihe (Die Bestätigungs-Buttons) with confirm_row: ui.button("Liga Beitreten", color="green", on_click=lambda e, p=player_id, s=place['gamesystem_id']: click_join_league(p, s)) # Der Abbrechen Button kriegt den gleichen Toggle-Befehl wie oben: ui.button(icon='cancel', color='red', on_click=lambda e, r1=join_row, r2=confirm_row: toggle_visibility(r1, r2)).props('round dense') else: # Spieler IST in der Liga! sys_card.classes("cursor-pointer hover:bg-zinc-800") # Auch hier machen wir es mit dem 'e' absolut sicher: sys_card.on('click', lambda e, name=place['gamesystem_name']: ui.navigate.to(f'/statistic/{name}')) # Wir zeigen die Stats. with ui.row().classes('items-center gap-4'): ui.label(text=f"MMR: {place['mmr']}") ui.label(text=f"Spiele: {place['games_in_system']}") # --------------------------- # Match Historie # --------------------------- with ui.card().classes("w-full"): ui.label(text= "Meine letzten Spiele").classes("font-bold text-white text-xl") # 1. Daten aus der DB holen raw_matches = data_api.get_recent_matches_for_player(player_id) # 2. Daten für die Tabelle aufbereiten table_rows = [] for match in raw_matches: # Bin ich Spieler 1 oder Spieler 2? if match['player1_id'] == player_id: # Ich bin Spieler 1, also ist Spieler 2 der Gegner opponent_name = f"{match['p2_display']} aka {match['p2_discord']}" my_score = match['score_player1'] opp_score = match['score_player2'] else: # Ich bin Spieler 2, also ist Spieler 1 der Gegner opponent_name = f"{match['p1_display']} aka {match['p1_discord']}" my_score = match['score_player2'] opp_score = match['score_player1'] # Gewonnen oder Verloren? if my_score > opp_score: result_text = "Gewonnen" elif my_score < opp_score: result_text = "Verloren" else: result_text = "Unentschieden" # Datum hübsch machen (schneidet die Millisekunden weg) date_clean = str(match['played_at'])[:10] # Eine fertige Zeile für unsere Tabelle bauen table_rows.append({ 'date': date_clean, 'system': match['gamesystem_name'], 'opponent': opponent_name, 'result': f"{result_text} ({my_score} : {opp_score})" }) # 3. Das Layout (Die Spalten) der Tabelle definieren table_columns = [ {'name': 'date', 'label': 'Gespielt am', 'field': 'date', 'align': 'left'}, {'name': 'system', 'label': 'System', 'field': 'system', 'align': 'left'}, {'name': 'opponent', 'label': 'Gegner', 'field': 'opponent', 'align': 'left'}, {'name': 'result', 'label': 'Ergebnis', 'field': 'result', 'align': 'left'} ] # 4. Die Tabelle zeichnen! if len(table_rows) > 0: ui.table(columns=table_columns, rows=table_rows, row_key='date').classes('w-full bg-zinc-900 text-white') else: ui.label("Noch keine Spiele absolviert.").classes("text-gray-500 italic")