import logging from typing import Optional, Callable from rio import Component, Text, Spacer, Rectangle, Column, TextStyle, Row, Button, TextInput, ThemeContextSwitcher from src.ezgg_lan_manager.services.TeamService import TeamService, NotMemberError, TeamLeadRemovalError, AlreadyMemberError, NameNotAllowedError, TeamNameTooLongError, \ TeamAbbrInvalidError, TeamNameAlreadyTaken from src.ezgg_lan_manager.types.Team import Team from src.ezgg_lan_manager.types.User import User logger = logging.getLogger(__name__.split(".")[-1]) class ErrorBox(Component): error_message: str cancel: Callable def build(self) -> Component: return Rectangle( content=Column( Text(self.error_message, style=TextStyle(fill=self.session.theme.background_color), margin_bottom=1.5), Row( Button( content="Ok", shape="rectangle", style="major", color="hud", on_press=self.cancel, ) ), margin=1 ), fill=self.session.theme.primary_color ) class TeamsDialogJoinHandler(Component): is_active: bool cancel: Callable user: Optional[User] = None team: Optional[Team] = None error_message: Optional[str] = None password: str = "" async def join(self) -> None: if self.user is None or self.team is None: return if self.password != self.team.join_password: self.error_message = "Falsches Passwort!" return try: await self.session[TeamService].add_member_to_team(self.team, self.user) except AlreadyMemberError: self.error_message = "Du bist bereits Mitglied dieses Teams" else: await self.cancel_with_reset() async def cancel_with_reset(self) -> None: await self.cancel() self.error_message = None self.password = "" def build(self) -> Component: if not self.is_active or self.user is None or self.team is None: return Spacer() if self.error_message is not None: return ErrorBox(error_message=self.error_message, cancel=self.cancel_with_reset) return Rectangle( content=Column( Text(f"Team {self.team.name} beitreten", style=TextStyle(fill=self.session.theme.background_color), margin_bottom=1, justify="center"), ThemeContextSwitcher(content=TextInput(text=self.bind().password, label="Beitrittspasswort", margin_bottom=1), color="secondary"), Row( Button( content="Abbrechen", shape="rectangle", style="major", color=self.session.theme.danger_color, on_press=self.cancel_with_reset, ), Button( content="Beitreten", shape="rectangle", style="major", color=self.session.theme.success_color, on_press=self.join, ), spacing=1 ), margin=1 ), fill=self.session.theme.primary_color ) class TeamsDialogLeaveHandler(Component): is_active: bool cancel: Callable user: Optional[User] = None team: Optional[Team] = None error_message: Optional[str] = None async def leave(self) -> None: if self.user is not None and self.team is not None: try: await self.session[TeamService].remove_member_from_team(self.team, self.user) except NotMemberError: self.error_message = "Du bist kein Mitglied in diesem Team" except TeamLeadRemovalError: self.error_message = "Als Teamleiter kannst du das Team nicht verlassen" else: await self.cancel_with_reset() async def cancel_with_reset(self) -> None: await self.cancel() self.error_message = None def build(self) -> Component: if not self.is_active or self.user is None or self.team is None: return Spacer() if self.error_message is not None: return ErrorBox(error_message=self.error_message, cancel=self.cancel_with_reset) return Rectangle( content=Column( Text(f"Team {self.team.name} wirklich verlassen?", style=TextStyle(fill=self.session.theme.background_color), margin_bottom=1.5, justify="center"), Row( Button( content="Nein", shape="rectangle", style="major", color=self.session.theme.danger_color, on_press=self.cancel_with_reset, ), Button( content="Ja", shape="rectangle", style="major", color=self.session.theme.success_color, on_press=self.leave, ), spacing=1 ), margin=1 ), fill=self.session.theme.primary_color ) class TeamsDialogCreateHandler(Component): is_active: bool cancel: Callable user: Optional[User] = None error_message: Optional[str] = None team_name: str = "" team_abbr: str = "" team_join_password: str = "" async def cancel_with_reset(self) -> None: await self.cancel() self.error_message = None self.team_name, self.team_abbr, self.team_join_password = "", "", "" async def create(self) -> None: if self.user is None: return if not self.team_name or not self.team_abbr or not self.team_join_password: self.error_message = "Angaben unvollständig" return try: await self.session[TeamService].create_team(self.team_name, self.team_abbr, self.team_join_password, self.user) except NameNotAllowedError as e: self.error_message = f"Angaben ungültig. Darf kein '{e.disallowed_char}' enthalten." except TeamNameTooLongError: self.error_message = f"Name zu lang. Maximal {TeamService.MAX_TEAM_NAME_LENGTH} Zeichen." except TeamAbbrInvalidError: self.error_message = f"Name zu lang. Maximal {TeamService.MAX_TEAM_ABBR_LENGTH} Zeichen." except TeamNameAlreadyTaken: self.error_message = "Ein Team mit diesem Namen existiert bereits." else: await self.cancel_with_reset() def build(self) -> Component: if not self.is_active or self.user is None: return Spacer() if self.error_message is not None: return ErrorBox(error_message=self.error_message, cancel=self.cancel_with_reset) return Rectangle( content=Column( Text(f"Team gründen", style=TextStyle(fill=self.session.theme.background_color), margin_bottom=1.5, justify="center"), ThemeContextSwitcher(content=TextInput(text=self.bind().team_name, label="Team Name", margin_bottom=1), color="secondary"), ThemeContextSwitcher(content=TextInput(text=self.bind().team_abbr, label="Team Abkürzung", margin_bottom=1), color="secondary"), ThemeContextSwitcher(content=TextInput(text=self.bind().team_join_password, label="Beitrittspasswort", margin_bottom=1), color="secondary"), Row( Button( content="Abbrechen", shape="rectangle", style="major", color=self.session.theme.danger_color, on_press=self.cancel_with_reset, ), Button( content="Gründen", shape="rectangle", style="major", color=self.session.theme.success_color, on_press=self.create, ), spacing=1 ), margin=1 ), fill=self.session.theme.primary_color )