import logging from dataclasses import field, dataclass from datetime import datetime from typing import Optional, Callable from rio import Column, Component, event, TextStyle, Text, Spacer, PointerEvent, Button, Popup, Card, Row from src.ez_lan_manager import ConfigurationService, CateringService, SeatingService, AccountingService from src.ez_lan_manager.components.CateringManagementOrderDisplay import CateringManagementOrderDisplay from src.ez_lan_manager.components.MainViewContentBox import MainViewContentBox from src.ez_lan_manager.types.CateringOrder import CateringOrder, CateringOrderStatus from src.ez_lan_manager.types.Seat import Seat logger = logging.getLogger(__name__.split(".")[-1]) class CateringOrderInfoPopup(Component): order: Optional[CateringOrder] = None close_cb: Optional[Callable] = None def build(self) -> Component: if not self.order: return Card( content=Text(""), margin=1, color=self.session.theme.hud_color, min_width=40, min_height=40, on_press=self.close_cb ) return Card( content=Column( Text(f"Bestellung {self.order.order_id}", style=TextStyle(font_size=1.2), margin_bottom=1), *[Row(Text(f"{amount}x"), Spacer(), Text(f"{item.name}")) for item, amount in self.order.items.items()], Spacer(), Row(Text("Gesamtpreis:"), Spacer(), Text(self.session[AccountingService].make_euro_string_from_int(self.order.price))) ), margin=1, color=self.session.theme.hud_color, min_width=40, min_height=40, on_press=self.close_cb, corner_radius=0.5 ) @dataclass class CateringOrderWithSeat: catering_order: CateringOrder seat: Optional[Seat] class ManageCateringPage(Component): all_orders: list[CateringOrderWithSeat] = field(default_factory=list) last_updated: Optional[datetime] = None order_popup_open: bool = False order_popup_order: Optional[CateringOrder] = None @event.on_populate async def on_populate(self) -> None: await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Catering Verwaltung") self.all_orders = await self.populate_seating(await self.session[CateringService].get_orders()) self.last_updated = datetime.now() @event.periodic(30) async def update_orders(self) -> None: polled_orders = await self.session[CateringService].get_orders() self.all_orders = await self.populate_seating(polled_orders) self.last_updated = datetime.now() async def populate_seating(self, orders: list[CateringOrder]) -> list[CateringOrderWithSeat]: result = [] for order in orders: seat = await self.session[SeatingService].get_user_seat(order.customer.user_id) result.append(CateringOrderWithSeat(catering_order=order, seat=seat)) return result def get_all_pending_orders(self) -> list[CateringOrderWithSeat]: filtered_list = list(filter(lambda o: o.catering_order.status != CateringOrderStatus.COMPLETED and o.catering_order.status != CateringOrderStatus.CANCELED, self.all_orders)) sorted_list = sorted(filtered_list, key=lambda o: o.catering_order.order_date) return sorted_list def get_all_completed_orders(self) -> list[CateringOrderWithSeat]: filtered_list = list(filter(lambda o: o.catering_order.status == CateringOrderStatus.COMPLETED or o.catering_order.status == CateringOrderStatus.CANCELED, self.all_orders)) sorted_list = sorted(filtered_list, key=lambda o: o.catering_order.order_date) return sorted_list async def order_clicked(self, order: CateringOrder, _: PointerEvent) -> None: self.order_popup_order = order self.order_popup_open = True async def close_cb(self) -> None: self.order_popup_open = False def build(self) -> Component: header_text = Text( text="Catering Verwaltung", style=TextStyle( fill=self.session.theme.background_color, font_size=1.2 ), margin_top=2, margin_bottom=2, align_x=0.5 ) popup = Popup( anchor=header_text, content=CateringOrderInfoPopup(order=self.order_popup_order, close_cb=self.close_cb), is_open=self.order_popup_open, position="bottom" ) return Column( MainViewContentBox( Column(popup) ), MainViewContentBox( Column( Text( text="Offene Bestellungen", style=TextStyle( fill=self.session.theme.background_color, font_size=1.2 ), margin_top=2, margin_bottom=0.2, align_x=0.5 ), Text( text=f"Letzte Aktualisierung: {'-' if not self.last_updated else self.last_updated.strftime('%H:%M:%S')}", style=TextStyle( fill=self.session.theme.background_color, font_size=0.7 ), margin_top=0.2, margin_bottom=0.2, align_x=0.5 ), Button( content=Text("Jetzt aktualisieren", style=TextStyle(font_size=0.7), justify="center"), shape="rectangle", margin_bottom=1, on_press=self.update_orders ), *[CateringManagementOrderDisplay(v.catering_order, v.seat, self.order_clicked) for v in self.get_all_pending_orders()], ) ), MainViewContentBox( Column( Text( text="Abgeschlossene Bestellungen", style=TextStyle( fill=self.session.theme.background_color, font_size=1.2 ), margin_top=2, margin_bottom=0.2, align_x=0.5 ), *[CateringManagementOrderDisplay(v.catering_order, v.seat, self.order_clicked) for v in self.get_all_completed_orders()], ) ), Spacer() )