add seating plan v2 (missing booking)

This commit is contained in:
David Rodenkirchen 2024-09-05 01:07:51 +02:00
parent acf458d629
commit c7c7cc7964
5 changed files with 136 additions and 50 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 0 B

After

Width:  |  Height:  |  Size: 100 KiB

View File

@ -1,12 +1,21 @@
from typing import Callable
from rio import Component, Rectangle, Grid
from src.ez_lan_manager.components.SeatingPlanPixels import SeatPixel, WallPixel, InvisiblePixel, TextPixel
from src.ez_lan_manager.types.Seat import Seat
MAX_GRID_WIDTH_PIXELS = 34
MAX_GRID_HEIGHT_PIXELS = 45
class SeatingPlan(Component):
seat_clicked_cb: Callable
seating_info: list[Seat]
def get_seat(self, seat_id: str) -> Seat:
return next(filter(lambda seat: seat.seat_id == seat_id, self.seating_info))
"""
This seating plan is for the community center "Bottenhorn"
"""
@ -26,60 +35,60 @@ class SeatingPlan(Component):
block_a_margin_left = 12
block_a_margin_top = 1
(grid
.add(SeatPixel("A01"), row=block_a_margin_top, column=block_a_margin_left, width=2, height=3)
.add(SeatPixel("A02"), row=block_a_margin_top + 4, column=block_a_margin_left, width=2, height=3)
.add(SeatPixel("A03"), row=block_a_margin_top + 8, column=block_a_margin_left, width=2, height=3)
.add(SeatPixel("A10"), row=block_a_margin_top, column=block_a_margin_left + 3, width=2, height=3)
.add(SeatPixel("A11"), row=block_a_margin_top + 4, column=block_a_margin_left + 3, width=2, height=3)
.add(SeatPixel("A12"), row=block_a_margin_top + 8, column=block_a_margin_left + 3, width=2, height=3)
.add(SeatPixel("A01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A01")), row=block_a_margin_top, column=block_a_margin_left, width=2, height=3)
.add(SeatPixel("A02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A02")), row=block_a_margin_top + 4, column=block_a_margin_left, width=2, height=3)
.add(SeatPixel("A03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A03")), row=block_a_margin_top + 8, column=block_a_margin_left, width=2, height=3)
.add(SeatPixel("A10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A10")), row=block_a_margin_top, column=block_a_margin_left + 3, width=2, height=3)
.add(SeatPixel("A11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A11")), row=block_a_margin_top + 4, column=block_a_margin_left + 3, width=2, height=3)
.add(SeatPixel("A12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("A12")), row=block_a_margin_top + 8, column=block_a_margin_left + 3, width=2, height=3)
)
# Block B
block_b_margin_left = 20
block_b_margin_top = 1
(grid
.add(SeatPixel("B01"), row=block_b_margin_top, column=block_b_margin_left, width=2, height=3)
.add(SeatPixel("B02"), row=block_b_margin_top + 4, column=block_b_margin_left, width=2, height=3)
.add(SeatPixel("B03"), row=block_b_margin_top + 8, column=block_b_margin_left, width=2, height=3)
.add(SeatPixel("B10"), row=block_b_margin_top, column=block_b_margin_left + 3, width=2, height=3)
.add(SeatPixel("B11"), row=block_b_margin_top + 4, column=block_b_margin_left + 3, width=2, height=3)
.add(SeatPixel("B12"), row=block_b_margin_top + 8, column=block_b_margin_left + 3, width=2, height=3)
.add(SeatPixel("B01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B01")), row=block_b_margin_top, column=block_b_margin_left, width=2, height=3)
.add(SeatPixel("B02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B02")), row=block_b_margin_top + 4, column=block_b_margin_left, width=2, height=3)
.add(SeatPixel("B03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B03")), row=block_b_margin_top + 8, column=block_b_margin_left, width=2, height=3)
.add(SeatPixel("B10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B10")), row=block_b_margin_top, column=block_b_margin_left + 3, width=2, height=3)
.add(SeatPixel("B11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B11")), row=block_b_margin_top + 4, column=block_b_margin_left + 3, width=2, height=3)
.add(SeatPixel("B12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("B12")), row=block_b_margin_top + 8, column=block_b_margin_left + 3, width=2, height=3)
)
# Block C
block_c_margin_left = 28
block_c_margin_top = 1
(grid
.add(SeatPixel("C01"), row=block_c_margin_top, column=block_c_margin_left, width=2, height=3)
.add(SeatPixel("C02"), row=block_c_margin_top + 4, column=block_c_margin_left, width=2, height=3)
.add(SeatPixel("C03"), row=block_c_margin_top + 8, column=block_c_margin_left, width=2, height=3)
.add(SeatPixel("C10"), row=block_c_margin_top, column=block_c_margin_left + 3, width=2, height=3)
.add(SeatPixel("C11"), row=block_c_margin_top + 4, column=block_c_margin_left + 3, width=2, height=3)
.add(SeatPixel("C12"), row=block_c_margin_top + 8, column=block_c_margin_left + 3, width=2, height=3)
.add(SeatPixel("C01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C01")), row=block_c_margin_top, column=block_c_margin_left, width=2, height=3)
.add(SeatPixel("C02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C02")), row=block_c_margin_top + 4, column=block_c_margin_left, width=2, height=3)
.add(SeatPixel("C03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C03")), row=block_c_margin_top + 8, column=block_c_margin_left, width=2, height=3)
.add(SeatPixel("C10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C10")), row=block_c_margin_top, column=block_c_margin_left + 3, width=2, height=3)
.add(SeatPixel("C11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C11")), row=block_c_margin_top + 4, column=block_c_margin_left + 3, width=2, height=3)
.add(SeatPixel("C12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("C12")), row=block_c_margin_top + 8, column=block_c_margin_left + 3, width=2, height=3)
)
# Block D
block_d_margin_left = 20
block_d_margin_top = 20
(grid
.add(SeatPixel("D01"), row=block_d_margin_top, column=block_d_margin_left, width=2, height=3)
.add(SeatPixel("D02"), row=block_d_margin_top + 4, column=block_d_margin_left, width=2, height=3)
.add(SeatPixel("D03"), row=block_d_margin_top + 8, column=block_d_margin_left, width=2, height=3)
.add(SeatPixel("D10"), row=block_d_margin_top, column=block_d_margin_left + 3, width=2, height=3)
.add(SeatPixel("D11"), row=block_d_margin_top + 4, column=block_d_margin_left + 3, width=2, height=3)
.add(SeatPixel("D12"), row=block_d_margin_top + 8, column=block_d_margin_left + 3, width=2, height=3)
.add(SeatPixel("D01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D01")), row=block_d_margin_top, column=block_d_margin_left, width=2, height=3)
.add(SeatPixel("D02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D02")), row=block_d_margin_top + 4, column=block_d_margin_left, width=2, height=3)
.add(SeatPixel("D03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D03")), row=block_d_margin_top + 8, column=block_d_margin_left, width=2, height=3)
.add(SeatPixel("D10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D10")), row=block_d_margin_top, column=block_d_margin_left + 3, width=2, height=3)
.add(SeatPixel("D11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D11")), row=block_d_margin_top + 4, column=block_d_margin_left + 3, width=2, height=3)
.add(SeatPixel("D12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("D12")), row=block_d_margin_top + 8, column=block_d_margin_left + 3, width=2, height=3)
)
# Block E
block_e_margin_left = 28
block_e_margin_top = 20
(grid
.add(SeatPixel("E01"), row=block_e_margin_top, column=block_e_margin_left, width=2, height=3)
.add(SeatPixel("E02"), row=block_e_margin_top + 4, column=block_e_margin_left, width=2, height=3)
.add(SeatPixel("E03"), row=block_e_margin_top + 8, column=block_e_margin_left, width=2, height=3)
.add(SeatPixel("E10"), row=block_e_margin_top, column=block_e_margin_left + 3, width=2, height=3)
.add(SeatPixel("E11"), row=block_e_margin_top + 4, column=block_e_margin_left + 3, width=2, height=3)
.add(SeatPixel("E12"), row=block_e_margin_top + 8, column=block_e_margin_left + 3, width=2, height=3)
.add(SeatPixel("E01", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E01")), row=block_e_margin_top, column=block_e_margin_left, width=2, height=3)
.add(SeatPixel("E02", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E02")), row=block_e_margin_top + 4, column=block_e_margin_left, width=2, height=3)
.add(SeatPixel("E03", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E03")), row=block_e_margin_top + 8, column=block_e_margin_left, width=2, height=3)
.add(SeatPixel("E10", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E10")), row=block_e_margin_top, column=block_e_margin_left + 3, width=2, height=3)
.add(SeatPixel("E11", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E11")), row=block_e_margin_top + 4, column=block_e_margin_left + 3, width=2, height=3)
.add(SeatPixel("E12", on_press_cb=self.seat_clicked_cb, seat=self.get_seat("E12")), row=block_e_margin_top + 8, column=block_e_margin_left + 3, width=2, height=3)
)
# Middle Wall
@ -100,7 +109,9 @@ class SeatingPlan(Component):
grid.add(TextPixel(icon_name="material/bed"), row=1, column=1, width=4, height=11)
# Toilet
grid.add(TextPixel(icon_name="material/wc"), row=1, column=7, width=3, height=4)
grid.add(TextPixel(icon_name="material/floor", no_outline=True), row=1, column=7, width=3, height=2)
grid.add(TextPixel(icon_name="material/north", no_outline=True), row=3, column=7, width=3, height=2)
grid.add(TextPixel(icon_name="material/wc"), row=5, column=7, width=3, height=2)
# Entry/Helpdesk
grid.add(TextPixel(text="Einlass\n &Orga"), row=19, column=3, width=7, height=5)

View File

@ -0,0 +1,26 @@
from typing import Optional
from rio import Component, Column, Text, TextStyle, Button, Spacer
from src.ez_lan_manager import AccountingService
class SeatingPlanInfoBox(Component):
seat_id: Optional[str] = None
seat_occupant: Optional[str] = None
seat_price: int = 0
is_blocked: bool = False
def build(self) -> Component:
if self.is_blocked:
return Column(Text(f"Sitzplatz gesperrt", margin=1, style=TextStyle(fill=self.session.theme.neutral_color, font_size=1.4), wrap=True, justify="center"), min_height=10)
if self.seat_id is None and self.seat_occupant is None:
return Column(Text(f"Sitzplatz auswählen...", margin=1, style=TextStyle(fill=self.session.theme.neutral_color), wrap=True, justify="center"), min_height=10)
return Column(
Text(f"Dieser Sitzplatz ({self.seat_id}) ist gebucht von:", margin=1, style=TextStyle(fill=self.session.theme.neutral_color), wrap=True, justify="center"),
Text(f"{self.seat_occupant}", margin_bottom=1, style=TextStyle(fill=self.session.theme.neutral_color, font_size=1.4), wrap=True, justify="center"),
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
)

View File

@ -1,21 +1,39 @@
from rio import Component, Text, Icon, TextStyle, Rectangle, Spacer, Color
from typing import Optional
from functools import partial
from rio import Component, Text, Icon, TextStyle, Rectangle, Spacer, Color, MouseEventListener
from typing import Optional, Callable
from src.ez_lan_manager.types.Seat import Seat
from src.ez_lan_manager.types.SessionStorage import SessionStorage
class SeatPixel(Component):
seat_id: str
on_press_cb: Callable
seat: Seat
def determine_color(self) -> Color:
if self.seat.user is not None and self.seat.user.user_id == self.session[SessionStorage].user_id:
return Color.from_hex("800080")
elif self.seat.is_blocked or self.seat.user is not None:
return self.session.theme.danger_color
return self.session.theme.success_color
def build(self) -> Component:
return Rectangle(
content=Text(self.seat_id, style=TextStyle(fill=self.session.theme.primary_color, font_size=0.7), align_x=0.5),
min_width=1,
min_height=1,
fill=self.session.theme.success_color,
hover_stroke_width = 0.1,
grow_x=True,
grow_y=True,
hover_fill=self.session.theme.hud_color,
transition_time=0.4
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),
min_width=1,
min_height=1,
fill=self.determine_color(),
hover_stroke_width = 0.1,
grow_x=True,
grow_y=True,
hover_fill=self.session.theme.hud_color,
transition_time=0.4,
ripple=True
),
on_press=partial(self.on_press_cb, self.seat_id)
)
class TextPixel(Component):
@ -25,7 +43,7 @@ class TextPixel(Component):
def build(self) -> Component:
if self.text is not None:
content = Text(self.text, style=TextStyle(fill=self.session.theme.neutral_color, font_size=1), align_x=0.5)
content = Text(self.text, style=TextStyle(fill=self.session.theme.neutral_color, font_size=1), align_x=0.5, selectable=False)
elif self.icon_name is not None:
content = Icon(self.icon_name, fill=self.session.theme.neutral_color)
else:
@ -40,8 +58,8 @@ class TextPixel(Component):
hover_stroke_width = None if self.no_outline else 0.1,
grow_x=True,
grow_y=True,
hover_fill=None if self.no_outline else self.session.theme.hud_color,
transition_time=0.4
hover_fill=None,
ripple=True
)
class WallPixel(Component):

View File

@ -1,21 +1,52 @@
from rio import Text, Column, TextStyle, Component, event
from typing import Optional
from src.ez_lan_manager import ConfigurationService
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.components.MainViewContentBox import MainViewContentBox
from src.ez_lan_manager.components.SeatingPlan import SeatingPlan
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
class SeatingPlanPage(Component):
seating_info: Optional[list[Seat]] = None
current_seat_id: Optional[str] = None
current_seat_occupant: Optional[str] = None
current_seat_price: int = 0
current_seat_is_blocked: 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()
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)
if not seat:
return
self.current_seat_is_blocked = seat.is_blocked
self.current_seat_id = seat.seat_id
ticket_info = self.session[TicketingService].get_ticket_info_by_category(seat.category)
price = 0 if not ticket_info else ticket_info.price
self.current_seat_price = price
if seat.user:
self.current_seat_occupant = seat.user.user_name
else:
self.current_seat_occupant = None
def build(self) -> Component:
return BasePage(
content=Column(
MainViewContentBox(Text("Sitzplatz Infobox", margin=1, style=TextStyle(fill=self.session.theme.neutral_color))),
MainViewContentBox(
SeatingPlan()
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)
),
align_y=0
),