From 871d8d6a3d8dc9ac01ff6d4abebda48be34ef4b0 Mon Sep 17 00:00:00 2001 From: David Rodenkirchen Date: Fri, 6 Sep 2024 12:22:40 +0200 Subject: [PATCH] add seating plan legend, improve ui --- src/ez_lan_manager/components/SeatingPlan.py | 61 ++++++++++++++++++- .../components/SeatingPlanInfoBox.py | 18 +++++- .../components/SeatingPlanPixels.py | 7 ++- src/ez_lan_manager/pages/SeatingPlanPage.py | 38 ++++++++++-- 4 files changed, 115 insertions(+), 9 deletions(-) diff --git a/src/ez_lan_manager/components/SeatingPlan.py b/src/ez_lan_manager/components/SeatingPlan.py index c194ce4..ee78842 100644 --- a/src/ez_lan_manager/components/SeatingPlan.py +++ b/src/ez_lan_manager/components/SeatingPlan.py @@ -1,6 +1,6 @@ from typing import Callable -from rio import Component, Rectangle, Grid +from rio import Component, Rectangle, Grid, Column, Row, Text, TextStyle, Color from src.ez_lan_manager.components.SeatingPlanPixels import SeatPixel, WallPixel, InvisiblePixel, TextPixel from src.ez_lan_manager.types.Seat import Seat @@ -8,6 +8,65 @@ from src.ez_lan_manager.types.Seat import Seat MAX_GRID_WIDTH_PIXELS = 34 MAX_GRID_HEIGHT_PIXELS = 45 +class SeatingPlanLegend(Component): + def build(self) -> Component: + return Column( + Text("Legende", style=TextStyle(fill=self.session.theme.neutral_color), justify="center", margin=1), + Row( + Text("L = Luxus Platz", justify="center", style=TextStyle(fill=self.session.theme.neutral_color)), + Text("N = Normaler Platz", justify="center", style=TextStyle(fill=self.session.theme.neutral_color)), + ), + Row( + Rectangle( + content=Column( + Text(f"Freier Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False), + Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5, + selectable=False, wrap=True) + ), + min_width=1, + min_height=1, + fill=self.session.theme.success_color, + grow_x=False, + grow_y=False, + hover_fill=self.session.theme.success_color, + transition_time=0.4, + ripple=True + ), + Rectangle( + content=Column( + Text(f"Belegter Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False), + Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5, + selectable=False, wrap=True) + ), + min_width=1, + min_height=1, + fill=self.session.theme.danger_color, + grow_x=False, + grow_y=False, + hover_fill=self.session.theme.danger_color, + transition_time=0.4, + ripple=True + ), + Rectangle( + content=Column( + Text(f"Eigener Platz", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False), + Text(f"", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5, + selectable=False, wrap=True) + ), + min_width=1, + min_height=1, + fill=Color.from_hex("800080"), + grow_x=False, + grow_y=False, + hover_fill=Color.from_hex("800080"), + transition_time=0.4, + ripple=True + ), + margin=1, + spacing=1 + ) + ) + class SeatingPlan(Component): seat_clicked_cb: Callable diff --git a/src/ez_lan_manager/components/SeatingPlanInfoBox.py b/src/ez_lan_manager/components/SeatingPlanInfoBox.py index 6a2bcd3..9bf347b 100644 --- a/src/ez_lan_manager/components/SeatingPlanInfoBox.py +++ b/src/ez_lan_manager/components/SeatingPlanInfoBox.py @@ -10,6 +10,7 @@ class SeatingPlanInfoBox(Component): seat_occupant: Optional[str] = None seat_price: int = 0 is_blocked: bool = False + user_has_seat: bool = False def build(self) -> Component: if self.is_blocked: @@ -22,5 +23,20 @@ class SeatingPlanInfoBox(Component): min_height=10 ) if self.seat_id and self.seat_occupant else Column( Text(f"Dieser Sitzplatz ({self.seat_id}) ist frei", margin=1, style=TextStyle(fill=self.session.theme.neutral_color), wrap=True, justify="center"), - Button(Text(f"Buchen ({AccountingService.make_euro_string_from_int(self.seat_price)})", margin=1, style=TextStyle(fill=self.session.theme.neutral_color, font_size=1.1), wrap=True, justify="center"), shape="rounded", style="major", color="secondary", margin=1, grow_y=False), min_height=10 + Button( + Text( + f"Buchen ({AccountingService.make_euro_string_from_int(self.seat_price)})", + margin=1, + style=TextStyle(fill=self.session.theme.neutral_color, font_size=1.1), + wrap=True, + justify="center" + ), + shape="rounded", + style="major", + color="secondary", + margin=1, + grow_y=False, + is_sensitive=not self.user_has_seat + ), + min_height=10 ) diff --git a/src/ez_lan_manager/components/SeatingPlanPixels.py b/src/ez_lan_manager/components/SeatingPlanPixels.py index 1f1013d..ea7189b 100644 --- a/src/ez_lan_manager/components/SeatingPlanPixels.py +++ b/src/ez_lan_manager/components/SeatingPlanPixels.py @@ -1,6 +1,6 @@ from functools import partial -from rio import Component, Text, Icon, TextStyle, Rectangle, Spacer, Color, MouseEventListener +from rio import Component, Text, Icon, TextStyle, Rectangle, Spacer, Color, MouseEventListener, Column from typing import Optional, Callable from src.ez_lan_manager.types.Seat import Seat @@ -22,7 +22,10 @@ class SeatPixel(Component): def build(self) -> Component: return MouseEventListener( content=Rectangle( - content=Text(self.seat_id, style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False), + content=Column( + Text(f"{self.seat_id}", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5, selectable=False), + Text(f"{self.seat.category[0]}", style=TextStyle(fill=self.session.theme.primary_color, font_size=0.9), align_x=0.5, selectable=False, wrap=True) + ), min_width=1, min_height=1, fill=self.determine_color(), diff --git a/src/ez_lan_manager/pages/SeatingPlanPage.py b/src/ez_lan_manager/pages/SeatingPlanPage.py index 4906586..9b9424e 100644 --- a/src/ez_lan_manager/pages/SeatingPlanPage.py +++ b/src/ez_lan_manager/pages/SeatingPlanPage.py @@ -1,14 +1,15 @@ from typing import Optional -from from_root import from_root from rio import Text, Column, TextStyle, Component, event, PressEvent, ProgressCircle, Row, Image, Button, Spacer -from src.ez_lan_manager import ConfigurationService, SeatingService, TicketingService +from src.ez_lan_manager import ConfigurationService, SeatingService, TicketingService, UserService from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox -from src.ez_lan_manager.components.SeatingPlan import SeatingPlan +from src.ez_lan_manager.components.SeatingPlan import SeatingPlan, SeatingPlanLegend from src.ez_lan_manager.components.SeatingPlanInfoBox import SeatingPlanInfoBox from src.ez_lan_manager.pages import BasePage from src.ez_lan_manager.types.Seat import Seat +from src.ez_lan_manager.types.SessionStorage import SessionStorage +from src.ez_lan_manager.types.User import User class SeatingPlanPage(Component): @@ -17,11 +18,21 @@ class SeatingPlanPage(Component): current_seat_occupant: Optional[str] = None current_seat_price: int = 0 current_seat_is_blocked: bool = False + user: Optional[User] = None + user_has_seat: bool = False @event.on_populate async def on_populate(self) -> None: await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Sitzplan") self.seating_info = await self.session[SeatingService].get_seating() + self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id) + user_has_seat = False + for seat in self.seating_info: + if not seat.user or not self.user: + continue + if seat.user.user_id == self.user.user_id: + user_has_seat = True + self.user_has_seat = user_has_seat async def on_seat_clicked(self, seat_id: str, _: PressEvent) -> None: seat = next(filter(lambda s: s.seat_id == seat_id, self.seating_info), None) @@ -38,15 +49,32 @@ class SeatingPlanPage(Component): self.current_seat_occupant = None def build(self) -> Component: + if not self.seating_info: + return BasePage( + content=Column( + MainViewContentBox( + ProgressCircle( + color="secondary", + align_x=0.5, + margin_top=2, + margin_bottom=2 + ) + ), + align_y=0 + ) + ) return BasePage( content=Column( + MainViewContentBox( + SeatingPlanInfoBox(seat_id=self.current_seat_id, seat_occupant=self.current_seat_occupant, seat_price=self.current_seat_price, + is_blocked=self.current_seat_is_blocked, user_has_seat=self.user_has_seat) + ), MainViewContentBox( SeatingPlan(seat_clicked_cb=self.on_seat_clicked, seating_info=self.seating_info) if self.seating_info else Column(ProgressCircle(color=self.session.theme.secondary_color, margin=3), Text("Sitzplan wird geladen", style=TextStyle(fill=self.session.theme.neutral_color), align_x=0.5, margin=1)) ), MainViewContentBox( - SeatingPlanInfoBox(seat_id=self.current_seat_id, seat_occupant=self.current_seat_occupant, seat_price=self.current_seat_price, - is_blocked=self.current_seat_is_blocked) + SeatingPlanLegend(), ), align_y=0 ),