Files
ELM/src/elm/components/NavigationBar.py
T
David Rodenkirchen 041ddaa334 Add participants page
2026-05-30 09:43:50 +00:00

146 lines
6.6 KiB
Python

from functools import partial
from typing import Optional, Callable
import rio
from from_root import from_root
from rio import Component, Row, Rectangle, Text, Color, Spacer, PointerEventListener, Column, Image, TextStyle, Icon, PointerEvent, EventHandler
from elm.services import ConfigurationService
class NavigationButton(Component):
icon: str
text: str
target_url: str
extension_state_changed: Optional[Callable]
new_tab: bool = False
current_rectangle_fill_color = Color.TRANSPARENT
current_text_fill_color = Color.from_hex("b9ccb2")
COLOR_ACTIVE_RECTANGLE = Color.from_hex("4EFBE5")
COLOR_ACTIVE_TEXT = Color.from_hex("4EFBE5")
COLOR_INACTIVE_RECTANGLE = Color.TRANSPARENT
COLOR_INACTIVE_TEXT = Color.from_hex("b9ccb2")
async def on_pointer_enter(self, _: PointerEvent) -> None:
self.current_rectangle_fill_color = self.COLOR_ACTIVE_RECTANGLE
self.current_text_fill_color = self.COLOR_ACTIVE_TEXT
self.force_refresh()
async def on_pointer_leave(self, _: PointerEvent) -> None:
self.current_rectangle_fill_color = self.COLOR_INACTIVE_RECTANGLE
self.current_text_fill_color = self.COLOR_INACTIVE_TEXT
self.force_refresh()
async def on_press(self, _: PointerEvent) -> None:
if self.new_tab:
self.session.open_url_in_browser(self.target_url)
else:
self.session.navigate_to(self.target_url)
if self.extension_state_changed is not None:
await self.extension_state_changed(None)
def is_active(self) -> bool:
return self.session.active_page_url.path == self.target_url
def build(self) -> Component:
return PointerEventListener(
Rectangle(
content=Row(
Rectangle(fill=self.COLOR_ACTIVE_RECTANGLE if self.is_active() else self.current_rectangle_fill_color, min_width=0.3, margin_right=1.7, transition_time=0.2),
Icon(
self.icon,
min_width=1.9,
min_height=1.9,
fill=self.COLOR_ACTIVE_TEXT if self.is_active() else self.current_text_fill_color
),
Text(
self.text,
style=TextStyle(fill=self.COLOR_ACTIVE_TEXT if self.is_active() else self.current_text_fill_color, font_weight="normal", font_size=1.1),
margin_left=1,
margin_top=1.3,
margin_bottom=1.3,
grow_x=True,
selectable=False
),
),
hover_shadow_radius=1,
hover_shadow_color=self.session.theme.primary_color_darker ,
hover_fill=self.session.theme.primary_color_darker ,
corner_radius=0.1,
cursor="pointer",
transition_time=0.2
),
on_pointer_enter=self.on_pointer_enter,
on_pointer_leave=self.on_pointer_leave,
on_press=self.on_press
)
class NavigationBar(Component):
extension_state_changed: EventHandler[bool]
is_extended: bool = False
async def on_extension_pressed(self, _: PointerEvent) -> None:
if self.session.is_mobile():
self.is_extended = not self.is_extended
await self.call_event_handler(partial(self.extension_state_changed, self.is_extended))
self.force_refresh()
def build(self) -> Component:
navigation = Column(
Column(
NavigationButton("material/house", "Startseite", "/", extension_state_changed=self.on_extension_pressed),
NavigationButton("material/local_activity", "Tickets", "/tickets", extension_state_changed=self.on_extension_pressed),
NavigationButton("material/chair_alt", "Sitzplan", "/seating", extension_state_changed=self.on_extension_pressed),
NavigationButton("material/group", "Teilnehmer", "/participants", extension_state_changed=self.on_extension_pressed),
NavigationButton("material/local_dining", "Catering", "/catering", extension_state_changed=self.on_extension_pressed),
NavigationButton("material/trophy", "Turniere", "/tournaments", extension_state_changed=self.on_extension_pressed),
margin_bottom=6
),
Column(
NavigationButton("material/help", "FAQ", "/faq", extension_state_changed=self.on_extension_pressed),
NavigationButton("material/contact_page", "Kontakt", "mailto:tech@ezgg-ev.de?subject=Kontaktanfrage", new_tab=True, extension_state_changed=self.on_extension_pressed),
NavigationButton("material/sports_bar", "EZ GG e.V.", "https://ezgg-ev.de", new_tab=True, extension_state_changed=None),
NavigationButton("material/article", "Impressum", "/imprint", extension_state_changed=self.on_extension_pressed),
NavigationButton("material/balance", "Regeln & AGB", "/rules", extension_state_changed=self.on_extension_pressed),
),
Spacer(),
Text(f"ELM v{self.session[ConfigurationService].APP_VERSION}", font_size=0.5, fill=self.session.theme.primary_color_darker),
margin=1
)
if self.session.is_mobile():
return Rectangle(
content=Column(
Row(
PointerEventListener(
Rectangle(
content=Icon("material/keyboard_double_arrow_left" if self.is_extended else "material/view_headline"),
cursor="pointer",
margin=0.5,
min_height=1.5,
min_width=1.5
),
on_press=self.on_extension_pressed
),
Spacer()
),
Spacer() if not self.is_extended else navigation,
Spacer()
),
fill=self.session.theme.box_color,
stroke_width=0.1,
stroke_color=self.session.theme.box_border_color,
min_width=self.session.screen_width if self.is_extended else 2
)
else: # Tablet % Desktop
return Rectangle(
content=navigation,
fill=self.session.theme.box_color,
stroke_width=0.1,
stroke_color=self.session.theme.box_border_color,
min_width=20
)