# -*- coding: utf-8 -*- """ Trainer SubView: Settings (F2). Schema-basiertes Formular fuer Trainings-Einstellungen. Felder werden dynamisch aus dem Settings-Schema des Trainers generiert. """ from __future__ import annotations from textual.app import ComposeResult from textual.containers import Vertical from textual.widgets import Static, Button, Input, Switch from trixy_core.tui.views.base import MainView class TrainerSettingsView(MainView): """F2 im Trainer-Kontext: Trainings-Einstellungen.""" TITLE = "Einstellungen" VIEW_ID = "trainer_settings" def __init__(self, **kwargs) -> None: super().__init__(**kwargs) self._trainer_data: dict = {} self._detail_data: object | None = None self._field_ids: list[str] = [] def set_trainer(self, trainer_data: dict) -> None: """Setzt die Trainer-Basisdaten.""" self._trainer_data = trainer_data self._detail_data = None self._field_ids = [] def compose(self) -> ComposeResult: with Vertical(classes="trainer-section"): yield Static("[bold]Einstellungen[/bold]", classes="trainer-section-header") yield Vertical(id="trainer-settings-form", classes="trainer-form-container") yield Button("Speichern", id="trainer-settings-save", variant="success") yield Static("", id="trainer-settings-status") async def on_activate(self) -> None: """Laedt Schema und aktuelle Werte.""" await self._load_detail() async def _load_detail(self) -> None: """Laedt Detail-Daten und baut das Formular auf.""" if not self.connection or not self._trainer_data: return trainer_id = self._trainer_data.get("trainer_id", "") if not trainer_id: return try: detail = await self.connection.request_trainer_detail(trainer_id) except Exception: return if detail is None or detail.error: return self._detail_data = detail await self._build_form(detail) async def _build_form(self, detail: object) -> None: """Baut das Formular aus dem Schema dynamisch auf.""" container = self.query_one("#trainer-settings-form", Vertical) # Alte Felder entfernen for child in list(container.children): await child.remove() self._field_ids = [] schema = getattr(detail, "settings_schema", {}) fields = schema.get("fields", []) if isinstance(schema, dict) else [] settings = getattr(detail, "settings", {}) for field_def in fields: name = field_def.get("name", "") or field_def.get("key", "") label = field_def.get("label", name) field_type = field_def.get("field_type", "") or field_def.get("type", "text") help_text = field_def.get("help_text", "") or field_def.get("help", "") default = field_def.get("default") current_value = settings.get(name, default) field_id = f"trainer-set-{name}" self._field_ids.append(field_id) # Label label_widget = Static(label, classes="trainer-field-label") await container.mount(label_widget) # Widget je nach Typ if field_type == "checkbox": widget = Switch(id=field_id, value=bool(current_value)) elif field_type == "number": is_float = field_def.get("is_float", False) input_type = "number" if is_float else "integer" val_str = str(current_value) if current_value is not None else "" widget = Input( id=field_id, value=val_str, placeholder=str(default) if default is not None else "", type=input_type, ) else: widget = Input( id=field_id, value=str(current_value) if current_value is not None else "", placeholder=field_def.get("placeholder", ""), ) await container.mount(widget) if help_text: help_widget = Static(f"[dim]{help_text}[/dim]", classes="trainer-field-help") await container.mount(help_widget) def collect_settings(self) -> dict: """Sammelt die Einstellungswerte aus dem Formular.""" if not self._detail_data: return {} schema = getattr(self._detail_data, "settings_schema", {}) fields = schema.get("fields", []) if isinstance(schema, dict) else [] result = {} for field_def in fields: name = field_def.get("name", "") or field_def.get("key", "") field_type = field_def.get("field_type", "") or field_def.get("type", "text") field_id = f"trainer-set-{name}" try: if field_type == "checkbox": widget = self.query_one(f"#{field_id}", Switch) result[name] = widget.value elif field_type == "number": widget = self.query_one(f"#{field_id}", Input) is_float = field_def.get("is_float", False) if is_float: result[name] = float(widget.value) if widget.value else 0.0 else: result[name] = int(widget.value) if widget.value else 0 else: widget = self.query_one(f"#{field_id}", Input) result[name] = widget.value except Exception: pass return result async def on_button_pressed(self, event: Button.Pressed) -> None: """Speichern-Button.""" if event.button.id != "trainer-settings-save": return status = self.query_one("#trainer-settings-status", Static) if not self.connection: status.update("[red]Keine Verbindung[/red]") return trainer_id = self._trainer_data.get("trainer_id", "") settings = self.collect_settings() try: status.update("[yellow]Speichern...[/yellow]") result = await self.connection.write_trainer_settings(trainer_id, settings) if result and result.success: status.update("[green]Einstellungen gespeichert[/green]") else: error = result.error if result else "Unbekannter Fehler" status.update(f"[red]Fehler: {error}[/red]") except Exception as e: status.update(f"[red]Fehler: {e}[/red]")